mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 21:53:35 +03:00
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:
parent
e00a26a11d
commit
06c8d8e31c
@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
import type * as dom from './dom';
|
||||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
|
||||
export interface AXNode {
|
||||
isInteresting(insideControl: boolean): boolean;
|
||||
isLeafNode(): boolean;
|
||||
isControl(): boolean;
|
||||
serialize(): types.SerializedAXNode;
|
||||
serialize(): channels.AXNode;
|
||||
children(): Iterable<AXNode>;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ export class Accessibility {
|
||||
async snapshot(options: {
|
||||
interestingOnly?: boolean;
|
||||
root?: dom.ElementHandle;
|
||||
} = {}): Promise<types.SerializedAXNode | null> {
|
||||
} = {}): Promise<channels.AXNode | null> {
|
||||
const {
|
||||
interestingOnly = true,
|
||||
root = null,
|
||||
@ -65,8 +65,8 @@ function collectInterestingNodes(collection: Set<AXNode>, node: AXNode, insideCo
|
||||
collectInterestingNodes(collection, child, insideControl);
|
||||
}
|
||||
|
||||
function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): types.SerializedAXNode[] {
|
||||
const children: types.SerializedAXNode[] = [];
|
||||
function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): channels.AXNode[] {
|
||||
const children: channels.AXNode[] = [];
|
||||
for (const child of node.children())
|
||||
children.push(...serializeTree(child, whitelistedNodes));
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { debug } from '../../utilsBundle';
|
||||
import type * as types from '../types';
|
||||
import { EventEmitter } from 'events';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
@ -34,13 +33,13 @@ import { PipeTransport } from '../../protocol/transport';
|
||||
import { RecentLogsCollector } from '../../common/debugLogger';
|
||||
import { gracefullyCloseSet } from '../../utils/processLauncher';
|
||||
import { TimeoutSettings } from '../../common/timeoutSettings';
|
||||
import type { AndroidWebView } from '../../protocol/channels';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { SdkObject, serverSideCallMetadata } from '../instrumentation';
|
||||
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
export interface Backend {
|
||||
devices(options: types.AndroidDeviceOptions): Promise<DeviceBackend[]>;
|
||||
devices(options: channels.AndroidDevicesOptions): Promise<DeviceBackend[]>;
|
||||
}
|
||||
|
||||
export interface DeviceBackend {
|
||||
@ -75,7 +74,7 @@ export class Android extends SdkObject {
|
||||
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 newSerials = new Set<string>();
|
||||
for (const d of devices) {
|
||||
@ -101,13 +100,13 @@ export class AndroidDevice extends SdkObject {
|
||||
readonly _backend: DeviceBackend;
|
||||
readonly model: string;
|
||||
readonly serial: string;
|
||||
private _options: types.AndroidDeviceOptions;
|
||||
private _options: channels.AndroidDevicesOptions;
|
||||
private _driverPromise: Promise<PipeTransport> | undefined;
|
||||
private _lastId = 0;
|
||||
private _callbacks = new Map<number, { fulfill: (result: any) => void, reject: (error: Error) => void }>();
|
||||
private _pollingWebViews: NodeJS.Timeout | undefined;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
private _webViews = new Map<string, AndroidWebView>();
|
||||
private _webViews = new Map<string, channels.AndroidWebView>();
|
||||
|
||||
static Events = {
|
||||
WebViewAdded: 'webViewAdded',
|
||||
@ -119,7 +118,7 @@ export class AndroidDevice extends SdkObject {
|
||||
private _android: Android;
|
||||
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');
|
||||
this._android = android;
|
||||
this._backend = backend;
|
||||
@ -129,7 +128,7 @@ export class AndroidDevice extends SdkObject {
|
||||
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();
|
||||
const model = await backend.runCommand('shell:getprop ro.product.model');
|
||||
const device = new AndroidDevice(android, backend, model.toString().trim(), options);
|
||||
@ -244,7 +243,7 @@ export class AndroidDevice extends SdkObject {
|
||||
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);
|
||||
await this._backend.runCommand(`shell:am force-stop ${pkg}`);
|
||||
const socketName = isUnderTest() ? 'webview_devtools_remote_playwright_test' : ('playwright-' + createGuid());
|
||||
@ -262,7 +261,7 @@ export class AndroidDevice extends SdkObject {
|
||||
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 androidBrowser = new AndroidBrowser(this, socket);
|
||||
await androidBrowser._init();
|
||||
@ -304,7 +303,7 @@ export class AndroidDevice extends SdkObject {
|
||||
return defaultContext;
|
||||
}
|
||||
|
||||
webViews(): AndroidWebView[] {
|
||||
webViews(): channels.AndroidWebView[] {
|
||||
return [...this._webViews.values()];
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import { debug } from '../../utilsBundle';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import * as net from 'net';
|
||||
import { EventEmitter } from 'events';
|
||||
import type { Backend, DeviceBackend, SocketBackend } from './android';
|
||||
import { assert, createGuid } from '../../utils';
|
||||
|
||||
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 lines = result.toString().trim().split('\n');
|
||||
return lines.map(line => {
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import { BrowserContext, validateBrowserContextOptions } from './browserContext';
|
||||
import { Page } from './page';
|
||||
import { Download } from './download';
|
||||
@ -48,7 +49,7 @@ export type BrowserOptions = PlaywrightOptions & {
|
||||
downloadsPath: string,
|
||||
tracesDir: string,
|
||||
headful?: boolean,
|
||||
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
|
||||
persistent?: channels.BrowserNewContextParams, // Undefined means no persistent context.
|
||||
browserProcess: BrowserProcess,
|
||||
customExecutablePath?: string;
|
||||
proxy?: ProxySettings,
|
||||
@ -75,13 +76,13 @@ export abstract class Browser extends SdkObject {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
abstract doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext>;
|
||||
abstract doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext>;
|
||||
abstract contexts(): BrowserContext[];
|
||||
abstract isConnected(): boolean;
|
||||
abstract version(): 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);
|
||||
const context = await this.doCreateNewContext(options);
|
||||
if (options.storageState)
|
||||
|
@ -29,6 +29,7 @@ import { Page, PageBinding } from './page';
|
||||
import type { Progress } from './progress';
|
||||
import type { Selectors } from './selectors';
|
||||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import type { CallMetadata } from './instrumentation';
|
||||
@ -54,7 +55,7 @@ export abstract class BrowserContext extends SdkObject {
|
||||
|
||||
readonly _timeoutSettings = new TimeoutSettings();
|
||||
readonly _pageBindings = new Map<string, PageBinding>();
|
||||
readonly _options: types.BrowserContextOptions;
|
||||
readonly _options: channels.BrowserNewContextParams;
|
||||
_requestInterceptor?: network.RouteHandler;
|
||||
private _isPersistentContext: boolean;
|
||||
private _closedStatus: 'open' | 'closing' | 'closed' = 'open';
|
||||
@ -74,7 +75,7 @@ export abstract class BrowserContext extends SdkObject {
|
||||
private _settingStorageState = false;
|
||||
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');
|
||||
this.attribution.context = this;
|
||||
this._browser = browser;
|
||||
@ -156,13 +157,13 @@ export abstract class BrowserContext extends SdkObject {
|
||||
// BrowserContext methods.
|
||||
abstract pages(): Page[];
|
||||
abstract newPageDelegate(): Promise<PageDelegate>;
|
||||
abstract addCookies(cookies: types.SetNetworkCookieParam[]): Promise<void>;
|
||||
abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise<void>;
|
||||
abstract clearCookies(): Promise<void>;
|
||||
abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>;
|
||||
abstract setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void>;
|
||||
abstract setOffline(offline: boolean): 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 doClearPermissions(): 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 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))
|
||||
urls = [ urls ];
|
||||
return await this.doGetCookies(urls as string[]);
|
||||
@ -374,8 +375,8 @@ export abstract class BrowserContext extends SdkObject {
|
||||
this._origins.add(origin);
|
||||
}
|
||||
|
||||
async storageState(): Promise<types.StorageState> {
|
||||
const result: types.StorageState = {
|
||||
async storageState(): Promise<channels.BrowserContextStorageStateResult> {
|
||||
const result: channels.BrowserContextStorageStateResult = {
|
||||
cookies: await this.cookies(),
|
||||
origins: []
|
||||
};
|
||||
@ -386,7 +387,7 @@ export abstract class BrowserContext extends SdkObject {
|
||||
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
||||
});
|
||||
for (const origin of this._origins) {
|
||||
const originStorage: types.OriginStorage = { origin, localStorage: [] };
|
||||
const originStorage: channels.OriginStorage = { origin, localStorage: [] };
|
||||
const frame = page.mainFrame();
|
||||
await frame.goto(internalMetadata, origin);
|
||||
const storage = await frame.evaluateExpression(`({
|
||||
@ -405,7 +406,7 @@ export abstract class BrowserContext extends SdkObject {
|
||||
return this._settingStorageState;
|
||||
}
|
||||
|
||||
async setStorageState(metadata: CallMetadata, state: types.SetStorageState) {
|
||||
async setStorageState(metadata: CallMetadata, state: NonNullable<channels.BrowserNewContextParams['storageState']>) {
|
||||
this._settingStorageState = true;
|
||||
try {
|
||||
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)
|
||||
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
|
||||
if (options.noDefaultViewport && options.isMobile !== undefined)
|
||||
|
@ -30,6 +30,7 @@ import { PipeTransport } from './pipeTransport';
|
||||
import type { Progress } from './progress';
|
||||
import { ProgressController } from './progress';
|
||||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings';
|
||||
import { debugMode } from '../utils';
|
||||
import { existsAsync } from '../utils/fileUtils';
|
||||
@ -73,10 +74,10 @@ export abstract class BrowserType extends SdkObject {
|
||||
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);
|
||||
const controller = new ProgressController(metadata, this);
|
||||
const persistent: types.BrowserContextOptions = options;
|
||||
const persistent: channels.BrowserNewContextParams = options;
|
||||
controller.setLogName('browser');
|
||||
const browser = await controller.run(progress => {
|
||||
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!;
|
||||
}
|
||||
|
||||
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 {
|
||||
return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir);
|
||||
} 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;
|
||||
const browserLogsCollector = new RecentLogsCollector();
|
||||
const { browserProcess, userDataDir, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir);
|
||||
|
@ -30,6 +30,7 @@ import { CRDevTools } from './crDevTools';
|
||||
import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
||||
import { Browser } from '../browser';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { HTTPRequestParams } from '../../common/netUtils';
|
||||
import { fetchData } from '../../common/netUtils';
|
||||
import { getUserAgent } from '../../common/userAgent';
|
||||
@ -94,7 +95,7 @@ export class Chromium extends BrowserType {
|
||||
await cleanedUp;
|
||||
};
|
||||
const browserProcess: BrowserProcess = { close: doClose, kill: doClose };
|
||||
const persistent: types.BrowserContextOptions = { noDefaultViewport: true };
|
||||
const persistent: channels.BrowserNewContextParams = { noDefaultViewport: true };
|
||||
const browserOptions: BrowserOptions = {
|
||||
...this._playwrightOptions,
|
||||
slowMo: options.slowMo,
|
||||
|
@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
|
||||
import type { Protocol } from './protocol';
|
||||
import type * as dom from '../dom';
|
||||
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}> {
|
||||
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();
|
||||
for (const property of this._payload.properties || [])
|
||||
properties.set(property.name.toLowerCase(), property.value.value);
|
||||
if (this._payload.description)
|
||||
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(),
|
||||
name: this._payload.name ? (this._payload.name.value || '') : '',
|
||||
};
|
||||
|
||||
const userStringProperties: Array<keyof types.SerializedAXNode> = [
|
||||
const userStringProperties: Array<keyof channels.AXNode> = [
|
||||
'description',
|
||||
'keyshortcuts',
|
||||
'roledescription',
|
||||
@ -233,7 +233,7 @@ class CRAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
node[userStringProperty] = properties.get(userStringProperty);
|
||||
}
|
||||
const booleanProperties: Array<keyof types.SerializedAXNode> = [
|
||||
const booleanProperties: Array<keyof channels.AXNode> = [
|
||||
'disabled',
|
||||
'expanded',
|
||||
'focused',
|
||||
@ -254,7 +254,7 @@ class CRAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
node[booleanProperty] = value;
|
||||
}
|
||||
const numericalProperties: Array<keyof types.SerializedAXNode> = [
|
||||
const numericalProperties: Array<keyof channels.AXNode> = [
|
||||
'level',
|
||||
'valuemax',
|
||||
'valuemin',
|
||||
@ -264,7 +264,7 @@ class CRAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
node[numericalProperty] = properties.get(numericalProperty);
|
||||
}
|
||||
const tokenProperties: Array<keyof types.SerializedAXNode> = [
|
||||
const tokenProperties: Array<keyof channels.AXNode> = [
|
||||
'autocomplete',
|
||||
'haspopup',
|
||||
'invalid',
|
||||
@ -277,7 +277,7 @@ class CRAXNode implements accessibility.AXNode {
|
||||
node[tokenProperty] = value;
|
||||
}
|
||||
|
||||
const axNode = node as types.SerializedAXNode;
|
||||
const axNode = node as channels.AXNode;
|
||||
if (this._payload.value) {
|
||||
if (typeof this._payload.value.value === 'string')
|
||||
axNode.valueString = this._payload.value.value;
|
||||
|
@ -26,6 +26,7 @@ import { Frame } from '../frames';
|
||||
import type { Dialog } from '../dialog';
|
||||
import type { ConnectionTransport } from '../transport';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { CRSession } from './crConnection';
|
||||
import { ConnectionEvents, CRConnection } from './crConnection';
|
||||
import { CRPage } from './crPage';
|
||||
@ -95,7 +96,7 @@ export class CRBrowser extends Browser {
|
||||
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;
|
||||
if (options.proxy) {
|
||||
if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK)
|
||||
@ -327,7 +328,7 @@ export class CRBrowserContext extends BrowserContext {
|
||||
|
||||
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);
|
||||
this._authenticateProxyViaCredentials();
|
||||
}
|
||||
@ -383,7 +384,7 @@ export class CRBrowserContext extends BrowserContext {
|
||||
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 });
|
||||
return network.filterCookies(cookies.map(c => {
|
||||
const copy: any = { sameSite: 'Lax', ...c };
|
||||
@ -393,11 +394,11 @@ export class CRBrowserContext extends BrowserContext {
|
||||
delete copy.sameParty;
|
||||
delete copy.sourceScheme;
|
||||
delete copy.sourcePort;
|
||||
return copy as types.NetworkCookie;
|
||||
return copy as channels.NetworkCookie;
|
||||
}), 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 });
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { Protocol } from './protocol';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { assert } from '../../utils';
|
||||
|
||||
export class CRCoverage {
|
||||
@ -31,19 +31,19 @@ export class CRCoverage {
|
||||
this._cssCoverage = new CSSCoverage(client);
|
||||
}
|
||||
|
||||
async startJSCoverage(options?: types.JSCoverageOptions) {
|
||||
async startJSCoverage(options: channels.PageStartJSCoverageParams) {
|
||||
return await this._jsCoverage.start(options);
|
||||
}
|
||||
|
||||
async stopJSCoverage(): Promise<types.JSCoverageEntry[]> {
|
||||
async stopJSCoverage(): Promise<channels.PageStopJSCoverageResult> {
|
||||
return await this._jsCoverage.stop();
|
||||
}
|
||||
|
||||
async startCSSCoverage(options?: types.CSSCoverageOptions) {
|
||||
async startCSSCoverage(options: channels.PageStartCSSCoverageParams) {
|
||||
return await this._cssCoverage.start(options);
|
||||
}
|
||||
|
||||
async stopCSSCoverage(): Promise<types.CSSCoverageEntry[]> {
|
||||
async stopCSSCoverage(): Promise<channels.PageStopCSSCoverageResult> {
|
||||
return await this._cssCoverage.stop();
|
||||
}
|
||||
}
|
||||
@ -66,7 +66,7 @@ class JSCoverage {
|
||||
this._resetOnNavigation = false;
|
||||
}
|
||||
|
||||
async start(options: types.JSCoverageOptions = {}) {
|
||||
async start(options: channels.PageStartJSCoverageParams) {
|
||||
assert(!this._enabled, 'JSCoverage is already enabled');
|
||||
const {
|
||||
resetOnNavigation = true,
|
||||
@ -112,7 +112,7 @@ class JSCoverage {
|
||||
this._scriptSources.set(event.scriptId, response.scriptSource);
|
||||
}
|
||||
|
||||
async stop(): Promise<types.JSCoverageEntry[]> {
|
||||
async stop(): Promise<channels.PageStopJSCoverageResult> {
|
||||
assert(this._enabled, 'JSCoverage is not enabled');
|
||||
this._enabled = false;
|
||||
const [profileResponse] = await Promise.all([
|
||||
@ -123,7 +123,7 @@ class JSCoverage {
|
||||
] as const);
|
||||
eventsHelper.removeEventListeners(this._eventListeners);
|
||||
|
||||
const coverage: types.JSCoverageEntry[] = [];
|
||||
const coverage: channels.PageStopJSCoverageResult = { entries: [] };
|
||||
for (const entry of profileResponse.result) {
|
||||
if (!this._scriptIds.has(entry.scriptId))
|
||||
continue;
|
||||
@ -131,9 +131,9 @@ class JSCoverage {
|
||||
continue;
|
||||
const source = this._scriptSources.get(entry.scriptId);
|
||||
if (source)
|
||||
coverage.push({ ...entry, source });
|
||||
coverage.entries.push({ ...entry, source });
|
||||
else
|
||||
coverage.push(entry);
|
||||
coverage.entries.push(entry);
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
@ -156,7 +156,7 @@ class CSSCoverage {
|
||||
this._resetOnNavigation = false;
|
||||
}
|
||||
|
||||
async start(options: types.CSSCoverageOptions = {}) {
|
||||
async start(options: channels.PageStartCSSCoverageParams) {
|
||||
assert(!this._enabled, 'CSSCoverage is already enabled');
|
||||
const { resetOnNavigation = true } = options;
|
||||
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');
|
||||
this._enabled = false;
|
||||
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()) {
|
||||
const url = this._stylesheetURLs.get(styleSheetId)!;
|
||||
const text = this._stylesheetSources.get(styleSheetId)!;
|
||||
const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []);
|
||||
coverage.push({ url, ranges, text });
|
||||
coverage.entries.push({ url, ranges, text });
|
||||
}
|
||||
|
||||
return coverage;
|
||||
|
@ -30,6 +30,7 @@ import type { PageBinding, PageDelegate } from '../page';
|
||||
import { Page, Worker } from '../page';
|
||||
import type { Progress } from '../progress';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { getAccessibilityTree } from './crAccessibility';
|
||||
import { CRBrowserContext } from './crBrowser';
|
||||
import type { CRSession } from './crConnection';
|
||||
@ -356,7 +357,7 @@ export class CRPage implements PageDelegate {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from '../../utils';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { CRSession } from './crConnection';
|
||||
import { readProtocolStream } from './crProtocolHelper';
|
||||
|
||||
@ -67,7 +67,7 @@ export class CRPDF {
|
||||
this._client = client;
|
||||
}
|
||||
|
||||
async generate(options: types.PDFOptions = {}): Promise<Buffer> {
|
||||
async generate(options: channels.PagePdfParams): Promise<Buffer> {
|
||||
const {
|
||||
scale = 1,
|
||||
displayHeaderFooter = false,
|
||||
|
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
|
||||
class Cookie {
|
||||
private _raw: types.NetworkCookie;
|
||||
constructor(data: types.NetworkCookie) {
|
||||
private _raw: channels.NetworkCookie;
|
||||
constructor(data: channels.NetworkCookie) {
|
||||
this._raw = data;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ class Cookie {
|
||||
this._raw.path === other._raw.path;
|
||||
}
|
||||
|
||||
networkCookie(): types.NetworkCookie {
|
||||
networkCookie(): channels.NetworkCookie {
|
||||
return this._raw;
|
||||
}
|
||||
|
||||
@ -61,12 +61,12 @@ class Cookie {
|
||||
export class CookieStore {
|
||||
private readonly _nameToCookies: Map<string, Set<Cookie>> = new Map();
|
||||
|
||||
addCookies(cookies: types.NetworkCookie[]) {
|
||||
addCookies(cookies: channels.NetworkCookie[]) {
|
||||
for (const cookie of cookies)
|
||||
this._addCookie(new Cookie(cookie));
|
||||
}
|
||||
|
||||
cookies(url: URL): types.NetworkCookie[] {
|
||||
cookies(url: URL): channels.NetworkCookie[] {
|
||||
const result = [];
|
||||
for (const cookie of this._cookiesIterator()) {
|
||||
if (cookie.matches(url))
|
||||
@ -75,7 +75,7 @@ export class CookieStore {
|
||||
return result;
|
||||
}
|
||||
|
||||
allCookies(): types.NetworkCookie[] {
|
||||
allCookies(): channels.NetworkCookie[] {
|
||||
const result = [];
|
||||
for (const cookie of this._cookiesIterator())
|
||||
result.push(cookie.networkCookie());
|
||||
|
@ -274,7 +274,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
|
||||
|
||||
async stopJSCoverage(params: channels.PageStopJSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopJSCoverageResult> {
|
||||
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> {
|
||||
@ -284,7 +284,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
|
||||
|
||||
async stopCSSCoverage(params: channels.PageStopCSSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopCSSCoverageResult> {
|
||||
const coverage = this._page.coverage as CRCoverage;
|
||||
return { entries: await coverage.stopCSSCoverage() };
|
||||
return await coverage.stopCSSCoverage();
|
||||
}
|
||||
|
||||
_onFrameAttached(frame: Frame) {
|
||||
|
@ -41,7 +41,6 @@ import * as readline from 'readline';
|
||||
import { RecentLogsCollector } from '../../common/debugLogger';
|
||||
import { serverSideCallMetadata, SdkObject } from '../instrumentation';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { BrowserContextOptions } from '../types';
|
||||
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
@ -211,7 +210,7 @@ export class Electron extends SdkObject {
|
||||
close: gracefullyClose,
|
||||
kill
|
||||
};
|
||||
const contextOptions: BrowserContextOptions = {
|
||||
const contextOptions: channels.BrowserNewContextParams = {
|
||||
...options,
|
||||
noDefaultViewport: true,
|
||||
};
|
||||
|
@ -52,7 +52,7 @@ export type APIRequestEvent = {
|
||||
url: URL,
|
||||
method: string,
|
||||
headers: { [name: string]: string },
|
||||
cookies: types.NameValueList,
|
||||
cookies: channels.NameValue[],
|
||||
postData?: Buffer
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@ export type APIRequestFinishedEvent = {
|
||||
requestEvent: APIRequestEvent,
|
||||
httpVersion: string;
|
||||
headers: http.IncomingHttpHeaders;
|
||||
cookies: types.NetworkCookie[];
|
||||
cookies: channels.NetworkCookie[];
|
||||
rawHeaders: string[];
|
||||
statusCode: number;
|
||||
statusMessage: string;
|
||||
@ -110,8 +110,8 @@ export abstract class APIRequestContext extends SdkObject {
|
||||
abstract dispose(): Promise<void>;
|
||||
|
||||
abstract _defaultOptions(): FetchRequestOptions;
|
||||
abstract _addCookies(cookies: types.NetworkCookie[]): Promise<void>;
|
||||
abstract _cookies(url: URL): Promise<types.NetworkCookie[]>;
|
||||
abstract _addCookies(cookies: channels.NetworkCookie[]): Promise<void>;
|
||||
abstract _cookies(url: URL): Promise<channels.NetworkCookie[]>;
|
||||
abstract storageState(): Promise<channels.APIRequestContextStorageStateResult>;
|
||||
|
||||
private _storeResponseBody(body: Buffer): string {
|
||||
@ -120,7 +120,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||
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 defaults = this._defaultOptions();
|
||||
headers['user-agent'] = defaults.userAgent;
|
||||
@ -194,16 +194,16 @@ export abstract class APIRequestContext extends SdkObject {
|
||||
return { ...fetchResponse, fetchUid };
|
||||
}
|
||||
|
||||
private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): types.NetworkCookie[] {
|
||||
private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): channels.NetworkCookie[] {
|
||||
if (!setCookie)
|
||||
return [];
|
||||
const url = new URL(responseUrl);
|
||||
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
|
||||
const defaultPath = '/' + url.pathname.substr(1).split('/').slice(0, -1).join('/');
|
||||
const cookies: types.NetworkCookie[] = [];
|
||||
const cookies: channels.NetworkCookie[] = [];
|
||||
for (const header of setCookie) {
|
||||
// Decode cookie value?
|
||||
const cookie: types.NetworkCookie | null = parseCookie(header);
|
||||
const cookie: channels.NetworkCookie | null = parseCookie(header);
|
||||
if (!cookie)
|
||||
continue;
|
||||
// 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);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
= (url.protocol === 'https:' ? https : http).request;
|
||||
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);
|
||||
}
|
||||
|
||||
async _cookies(url: URL): Promise<types.NetworkCookie[]> {
|
||||
async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
|
||||
return await this._context.cookies(url.toString());
|
||||
}
|
||||
|
||||
@ -519,11 +519,11 @@ export class GlobalAPIRequestContext extends APIRequestContext {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
async _addCookies(cookies: types.NetworkCookie[]): Promise<void> {
|
||||
async _addCookies(cookies: channels.NetworkCookie[]): Promise<void> {
|
||||
this._cookieStore.addCookies(cookies);
|
||||
}
|
||||
|
||||
async _cookies(url: URL): Promise<types.NetworkCookie[]> {
|
||||
async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
|
||||
return this._cookieStore.cookies(url);
|
||||
}
|
||||
|
||||
@ -544,7 +544,7 @@ function toHeadersArray(rawHeaders: string[]): types.HeadersArray {
|
||||
|
||||
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 => {
|
||||
let key = '';
|
||||
let value = '';
|
||||
@ -563,7 +563,7 @@ function parseCookie(header: string): types.NetworkCookie | null {
|
||||
if (!pairs.length)
|
||||
return null;
|
||||
const [name, value] = pairs[0];
|
||||
const cookie: types.NetworkCookie = {
|
||||
const cookie: channels.NetworkCookie = {
|
||||
name,
|
||||
value,
|
||||
domain: '',
|
||||
|
@ -19,7 +19,7 @@ import type * as accessibility from '../accessibility';
|
||||
import type { FFSession } from './ffConnection';
|
||||
import type { Protocol } from './protocol';
|
||||
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}> {
|
||||
const objectId = needle ? needle._objectId : undefined;
|
||||
@ -198,12 +198,12 @@ class FFAXNode implements accessibility.AXNode {
|
||||
return this.isLeafNode() && !!this._name.trim();
|
||||
}
|
||||
|
||||
serialize(): types.SerializedAXNode {
|
||||
const node: {[x in keyof types.SerializedAXNode]: any} = {
|
||||
serialize(): channels.AXNode {
|
||||
const node: {[x in keyof channels.AXNode]: any} = {
|
||||
role: FFRoleToARIARole.get(this._role) || this._role,
|
||||
name: this._name || '',
|
||||
};
|
||||
const userStringProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
|
||||
const userStringProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
|
||||
'name',
|
||||
'description',
|
||||
'roledescription',
|
||||
@ -215,7 +215,7 @@ class FFAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
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',
|
||||
'expanded',
|
||||
'focused',
|
||||
@ -234,7 +234,7 @@ class FFAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
node[booleanProperty] = value;
|
||||
}
|
||||
const numericalProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
|
||||
const numericalProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
|
||||
'level'
|
||||
];
|
||||
for (const numericalProperty of numericalProperties) {
|
||||
@ -242,7 +242,7 @@ class FFAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
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',
|
||||
'haspopup',
|
||||
'invalid',
|
||||
@ -255,7 +255,7 @@ class FFAXNode implements accessibility.AXNode {
|
||||
node[tokenProperty] = value;
|
||||
}
|
||||
|
||||
const axNode = node as types.SerializedAXNode;
|
||||
const axNode = node as channels.AXNode;
|
||||
axNode.valueString = this._payload.value;
|
||||
if ('checked' in this._payload)
|
||||
axNode.checked = this._payload.checked === true ? 'checked' : this._payload.checked === 'mixed' ? 'mixed' : 'unchecked';
|
||||
|
@ -24,6 +24,7 @@ import * as network from '../network';
|
||||
import type { Page, PageBinding, PageDelegate } from '../page';
|
||||
import type { ConnectionTransport } from '../transport';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { ConnectionEvents, FFConnection } from './ffConnection';
|
||||
import { FFPage } from './ffPage';
|
||||
import type { Protocol } from './protocol';
|
||||
@ -77,7 +78,7 @@ export class FFBrowser extends Browser {
|
||||
return !this._connection._closed;
|
||||
}
|
||||
|
||||
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
|
||||
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
||||
if (options.isMobile)
|
||||
throw new Error('options.isMobile is not supported in Firefox');
|
||||
const { browserContextId } = await this._connection.send('Browser.createBrowserContext', { removeOnDetach: true });
|
||||
@ -155,7 +156,7 @@ export class FFBrowser extends Browser {
|
||||
export class FFBrowserContext extends BrowserContext {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -255,17 +256,17 @@ export class FFBrowserContext extends BrowserContext {
|
||||
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 });
|
||||
return network.filterCookies(cookies.map(c => {
|
||||
const copy: any = { ... c };
|
||||
delete copy.size;
|
||||
delete copy.session;
|
||||
return copy as types.NetworkCookie;
|
||||
return copy as channels.NetworkCookie;
|
||||
}), urls);
|
||||
}
|
||||
|
||||
async addCookies(cookies: types.SetNetworkCookieParam[]) {
|
||||
async addCookies(cookies: channels.SetNetworkCookie[]) {
|
||||
const cc = network.rewriteCookies(cookies).map(c => ({
|
||||
...c,
|
||||
expires: c.expires && c.expires !== -1 ? c.expires : undefined,
|
||||
|
@ -20,16 +20,16 @@ import { Artifact } from '../artifact';
|
||||
import type { BrowserContext } from '../browserContext';
|
||||
import type * as har from './har';
|
||||
import { HarTracer } from './harTracer';
|
||||
import type { HarOptions } from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
|
||||
export class HarRecorder {
|
||||
private _artifact: Artifact;
|
||||
private _isFlushed: boolean = false;
|
||||
private _options: HarOptions;
|
||||
private _options: channels.RecordHarOptions;
|
||||
private _tracer: HarTracer;
|
||||
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._options = options;
|
||||
const urlFilterRe = options.urlRegexSource !== undefined && options.urlRegexFlags !== undefined ? new RegExp(options.urlRegexSource, options.urlRegexFlags) : undefined;
|
||||
|
@ -23,7 +23,7 @@ import { SdkObject } from './instrumentation';
|
||||
import type { NameValue } from '../common/types';
|
||||
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));
|
||||
// Chromiums's cookies are missing sameSite when it is 'None'
|
||||
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)
|
||||
const kMaxCookieExpiresDateInSeconds = 253402300799;
|
||||
|
||||
export function rewriteCookies(cookies: types.SetNetworkCookieParam[]): types.SetNetworkCookieParam[] {
|
||||
export function rewriteCookies(cookies: channels.SetNetworkCookie[]): channels.SetNetworkCookie[] {
|
||||
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), 'Cookie should have either url or domain');
|
||||
|
@ -20,6 +20,7 @@ import * as frames from './frames';
|
||||
import * as input from './input';
|
||||
import * as js from './javascript';
|
||||
import * as network from './network';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import type { ScreenshotOptions } from './screenshotter';
|
||||
import { Screenshotter, validateScreenshotOptions } from './screenshotter';
|
||||
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||
@ -86,7 +87,7 @@ export interface PageDelegate {
|
||||
setScreencastOptions(options: { width: number, height: number, quality: number } | null): Promise<void>;
|
||||
|
||||
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;
|
||||
|
||||
// Work around WebKit's raf issues on Windows.
|
||||
@ -160,7 +161,7 @@ export class Page extends SdkObject {
|
||||
readonly _frameManager: frames.FrameManager;
|
||||
readonly accessibility: accessibility.Accessibility;
|
||||
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;
|
||||
private _clientRequestInterceptor: network.RouteHandler | undefined;
|
||||
private _serverRequestInterceptor: network.RouteHandler | undefined;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import type { Size, Point, 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 = {
|
||||
strict?: boolean,
|
||||
@ -77,16 +78,12 @@ export type FilePayload = {
|
||||
};
|
||||
|
||||
export type MediaType = 'screen' | 'print';
|
||||
export const mediaTypes: Set<MediaType> = new Set(['screen', 'print']);
|
||||
|
||||
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 const reducedMotions: Set<ReducedMotion> = new Set(['no-preference', 'reduce']);
|
||||
|
||||
export type ForcedColors = 'active' | 'none';
|
||||
export const forcedColors: Set<ForcedColors> = new Set(['active', 'none']);
|
||||
|
||||
export type DeviceDescriptor = {
|
||||
userAgent: string,
|
||||
@ -98,56 +95,6 @@ export type 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 = {
|
||||
server: string,
|
||||
bypass?: string,
|
||||
@ -202,180 +149,14 @@ export type NormalizedContinueOverrides = {
|
||||
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 HarOptions = {
|
||||
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 LaunchOptions = channels.BrowserTypeLaunchOptions & { useWebSocket?: boolean };
|
||||
|
||||
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 = {
|
||||
url: string,
|
||||
lineNumber: 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,
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ import type * as accessibility from '../accessibility';
|
||||
import type { WKSession } from './wkConnection';
|
||||
import type { Protocol } from './protocol';
|
||||
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) {
|
||||
const objectId = needle ? needle._objectId : undefined;
|
||||
@ -167,8 +167,8 @@ class WKAXNode implements accessibility.AXNode {
|
||||
return false;
|
||||
}
|
||||
|
||||
serialize(): types.SerializedAXNode {
|
||||
const node: types.SerializedAXNode = {
|
||||
serialize(): channels.AXNode {
|
||||
const node: channels.AXNode = {
|
||||
role: WKRoleToARIARole.get(this._payload.role) || this._payload.role,
|
||||
name: this._name(),
|
||||
};
|
||||
@ -195,7 +195,7 @@ class WKAXNode implements accessibility.AXNode {
|
||||
if ('pressed' in this._payload)
|
||||
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',
|
||||
'valuetext'
|
||||
];
|
||||
@ -205,7 +205,7 @@ class WKAXNode implements accessibility.AXNode {
|
||||
(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',
|
||||
'expanded',
|
||||
'focused',
|
||||
@ -227,7 +227,7 @@ class WKAXNode implements accessibility.AXNode {
|
||||
(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',
|
||||
'valuemax',
|
||||
'valuemin',
|
||||
@ -237,7 +237,7 @@ class WKAXNode implements accessibility.AXNode {
|
||||
continue;
|
||||
(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',
|
||||
'haspopup',
|
||||
'invalid',
|
||||
|
@ -25,6 +25,7 @@ import * as network from '../network';
|
||||
import type { Page, PageBinding, PageDelegate } from '../page';
|
||||
import type { ConnectionTransport } from '../transport';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { Protocol } from './protocol';
|
||||
import type { PageProxyMessageReceivedPayload } from './wkConnection';
|
||||
import { kPageProxyMessageReceived, WKConnection, WKSession } from './wkConnection';
|
||||
@ -82,7 +83,7 @@ export class WKBrowser extends Browser {
|
||||
this._didClose();
|
||||
}
|
||||
|
||||
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
|
||||
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
||||
const createOptions = options.proxy ? {
|
||||
proxyServer: options.proxy.server,
|
||||
proxyBypassList: options.proxy.bypass
|
||||
@ -206,7 +207,7 @@ export class WKBrowser extends Browser {
|
||||
export class WKBrowserContext extends BrowserContext {
|
||||
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);
|
||||
this._authenticateProxyViaHeader();
|
||||
}
|
||||
@ -249,17 +250,17 @@ export class WKBrowserContext extends BrowserContext {
|
||||
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 });
|
||||
return network.filterCookies(cookies.map((c: types.NetworkCookie) => {
|
||||
return network.filterCookies(cookies.map((c: channels.NetworkCookie) => {
|
||||
const copy: any = { ... c };
|
||||
copy.expires = c.expires === -1 ? -1 : c.expires / 1000;
|
||||
delete copy.session;
|
||||
return copy as types.NetworkCookie;
|
||||
return copy as channels.NetworkCookie;
|
||||
}), urls);
|
||||
}
|
||||
|
||||
async addCookies(cookies: types.SetNetworkCookieParam[]) {
|
||||
async addCookies(cookies: channels.SetNetworkCookie[]) {
|
||||
const cc = network.rewriteCookies(cookies).map(c => ({
|
||||
...c,
|
||||
session: c.expires === -1 || c.expires === undefined,
|
||||
|
Loading…
Reference in New Issue
Block a user