From 06c8d8e31c0acab34f6cfc3fa506ce67f76a849a Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 14 Jun 2022 22:02:15 -0700 Subject: [PATCH] chore: use channels types instead of a copy in server (#14874) This is to avoid duplicating types for no reason. --- .../src/server/accessibility.ts | 10 +- .../src/server/android/android.ts | 21 +- .../src/server/android/backendAdb.ts | 4 +- .../playwright-core/src/server/browser.ts | 7 +- .../src/server/browserContext.ts | 21 +- .../playwright-core/src/server/browserType.ts | 9 +- .../src/server/chromium/chromium.ts | 3 +- .../src/server/chromium/crAccessibility.ts | 16 +- .../src/server/chromium/crBrowser.ts | 11 +- .../src/server/chromium/crCoverage.ts | 28 +-- .../src/server/chromium/crPage.ts | 3 +- .../src/server/chromium/crPdf.ts | 4 +- .../playwright-core/src/server/cookieStore.ts | 14 +- .../src/server/dispatchers/pageDispatcher.ts | 4 +- .../src/server/electron/electron.ts | 3 +- packages/playwright-core/src/server/fetch.ts | 32 +-- .../src/server/firefox/ffAccessibility.ts | 16 +- .../src/server/firefox/ffBrowser.ts | 11 +- .../src/server/har/harRecorder.ts | 6 +- .../playwright-core/src/server/network.ts | 4 +- packages/playwright-core/src/server/page.ts | 5 +- packages/playwright-core/src/server/types.ts | 223 +----------------- .../src/server/webkit/wkAccessibility.ts | 14 +- .../src/server/webkit/wkBrowser.ts | 13 +- 24 files changed, 135 insertions(+), 347 deletions(-) diff --git a/packages/playwright-core/src/server/accessibility.ts b/packages/playwright-core/src/server/accessibility.ts index 5e8daf0ffd..a217b02b0d 100644 --- a/packages/playwright-core/src/server/accessibility.ts +++ b/packages/playwright-core/src/server/accessibility.ts @@ -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; } @@ -35,7 +35,7 @@ export class Accessibility { async snapshot(options: { interestingOnly?: boolean; root?: dom.ElementHandle; - } = {}): Promise { + } = {}): Promise { const { interestingOnly = true, root = null, @@ -65,8 +65,8 @@ function collectInterestingNodes(collection: Set, node: AXNode, insideCo collectInterestingNodes(collection, child, insideControl); } -function serializeTree(node: AXNode, whitelistedNodes?: Set): types.SerializedAXNode[] { - const children: types.SerializedAXNode[] = []; +function serializeTree(node: AXNode, whitelistedNodes?: Set): channels.AXNode[] { + const children: channels.AXNode[] = []; for (const child of node.children()) children.push(...serializeTree(child, whitelistedNodes)); diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts index d8e46cbc41..bf26c93b7c 100644 --- a/packages/playwright-core/src/server/android/android.ts +++ b/packages/playwright-core/src/server/android/android.ts @@ -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; + devices(options: channels.AndroidDevicesOptions): Promise; } export interface DeviceBackend { @@ -75,7 +74,7 @@ export class Android extends SdkObject { this._timeoutSettings.setDefaultTimeout(timeout); } - async devices(options: types.AndroidDeviceOptions): Promise { + async devices(options: channels.AndroidDevicesOptions): Promise { const devices = (await this._backend.devices(options)).filter(d => d.status === 'device'); const newSerials = new Set(); 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 | undefined; private _lastId = 0; private _callbacks = new Map void, reject: (error: Error) => void }>(); private _pollingWebViews: NodeJS.Timeout | undefined; readonly _timeoutSettings: TimeoutSettings; - private _webViews = new Map(); + private _webViews = new Map(); 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 { + static async create(android: Android, backend: DeviceBackend, options: channels.AndroidDevicesOptions): Promise { 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 { + async launchBrowser(pkg: string = 'com.android.chrome', options: channels.BrowserNewContextParams): Promise { 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 { + private async _connectToBrowser(socketName: string, options: channels.BrowserNewContextParams = {}): Promise { 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()]; } diff --git a/packages/playwright-core/src/server/android/backendAdb.ts b/packages/playwright-core/src/server/android/backendAdb.ts index 754e62261f..9874906791 100644 --- a/packages/playwright-core/src/server/android/backendAdb.ts +++ b/packages/playwright-core/src/server/android/backendAdb.ts @@ -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 { + async devices(options: channels.AndroidDevicesOptions = {}): Promise { const result = await runCommand('host:devices', options.host, options.port); const lines = result.toString().trim().split('\n'); return lines.map(line => { diff --git a/packages/playwright-core/src/server/browser.ts b/packages/playwright-core/src/server/browser.ts index e108978c68..1e5858f666 100644 --- a/packages/playwright-core/src/server/browser.ts +++ b/packages/playwright-core/src/server/browser.ts @@ -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; + abstract doCreateNewContext(options: channels.BrowserNewContextParams): Promise; abstract contexts(): BrowserContext[]; abstract isConnected(): boolean; abstract version(): string; abstract userAgent(): string; - async newContext(metadata: CallMetadata, options: types.BrowserContextOptions): Promise { + async newContext(metadata: CallMetadata, options: channels.BrowserNewContextParams): Promise { validateBrowserContextOptions(options, this.options); const context = await this.doCreateNewContext(options); if (options.storageState) diff --git a/packages/playwright-core/src/server/browserContext.ts b/packages/playwright-core/src/server/browserContext.ts index fdc24a6bd9..bee4294533 100644 --- a/packages/playwright-core/src/server/browserContext.ts +++ b/packages/playwright-core/src/server/browserContext.ts @@ -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(); - 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; - abstract addCookies(cookies: types.SetNetworkCookieParam[]): Promise; + abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise; abstract clearCookies(): Promise; abstract setGeolocation(geolocation?: types.Geolocation): Promise; abstract setExtraHTTPHeaders(headers: types.HeadersArray): Promise; abstract setOffline(offline: boolean): Promise; abstract cancelDownload(uuid: string): Promise; - protected abstract doGetCookies(urls: string[]): Promise; + protected abstract doGetCookies(urls: string[]): Promise; protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise; protected abstract doClearPermissions(): Promise; protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise; @@ -174,7 +175,7 @@ export abstract class BrowserContext extends SdkObject { protected abstract doClose(): Promise; protected abstract onClosePersistent(): void; - async cookies(urls: string | string[] | undefined = []): Promise { + async cookies(urls: string | string[] | undefined = []): Promise { 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 { - const result: types.StorageState = { + async storageState(): Promise { + const result: channels.BrowserContextStorageStateResult = { cookies: await this.cookies(), origins: [] }; @@ -386,7 +387,7 @@ export abstract class BrowserContext extends SdkObject { handler.fulfill({ body: '' }).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) { 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) diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index dc1cf213ca..8df03bb9f1 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -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 { + async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: channels.BrowserTypeLaunchPersistentContextOptions & { useWebSocket?: boolean }): Promise { 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 { + async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise { 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 { + async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise { 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); diff --git a/packages/playwright-core/src/server/chromium/chromium.ts b/packages/playwright-core/src/server/chromium/chromium.ts index f4a7b0d12d..ad2deee6eb 100644 --- a/packages/playwright-core/src/server/chromium/chromium.ts +++ b/packages/playwright-core/src/server/chromium/chromium.ts @@ -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, diff --git a/packages/playwright-core/src/server/chromium/crAccessibility.ts b/packages/playwright-core/src/server/chromium/crAccessibility.ts index 5709539e48..aeb5ebd724 100644 --- a/packages/playwright-core/src/server/chromium/crAccessibility.ts +++ b/packages/playwright-core/src/server/chromium/crAccessibility.ts @@ -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 = 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 = [ + const userStringProperties: Array = [ 'description', 'keyshortcuts', 'roledescription', @@ -233,7 +233,7 @@ class CRAXNode implements accessibility.AXNode { continue; node[userStringProperty] = properties.get(userStringProperty); } - const booleanProperties: Array = [ + const booleanProperties: Array = [ 'disabled', 'expanded', 'focused', @@ -254,7 +254,7 @@ class CRAXNode implements accessibility.AXNode { continue; node[booleanProperty] = value; } - const numericalProperties: Array = [ + const numericalProperties: Array = [ 'level', 'valuemax', 'valuemin', @@ -264,7 +264,7 @@ class CRAXNode implements accessibility.AXNode { continue; node[numericalProperty] = properties.get(numericalProperty); } - const tokenProperties: Array = [ + const tokenProperties: Array = [ '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; diff --git a/packages/playwright-core/src/server/chromium/crBrowser.ts b/packages/playwright-core/src/server/chromium/crBrowser.ts index 2cd01d22e0..4423aaa6bc 100644 --- a/packages/playwright-core/src/server/chromium/crBrowser.ts +++ b/packages/playwright-core/src/server/chromium/crBrowser.ts @@ -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 { + async doCreateNewContext(options: channels.BrowserNewContextParams): Promise { 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 { + async doGetCookies(urls: string[]): Promise { 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 }); } diff --git a/packages/playwright-core/src/server/chromium/crCoverage.ts b/packages/playwright-core/src/server/chromium/crCoverage.ts index 9f91e11ac0..793ca16bb7 100644 --- a/packages/playwright-core/src/server/chromium/crCoverage.ts +++ b/packages/playwright-core/src/server/chromium/crCoverage.ts @@ -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 { + async stopJSCoverage(): Promise { return await this._jsCoverage.stop(); } - async startCSSCoverage(options?: types.CSSCoverageOptions) { + async startCSSCoverage(options: channels.PageStartCSSCoverageParams) { return await this._cssCoverage.start(options); } - async stopCSSCoverage(): Promise { + async stopCSSCoverage(): Promise { 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 { + async stop(): Promise { 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 { + async stop(): Promise { 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; diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index ae97243072..791203a23b 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -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 { + async pdf(options: channels.PagePdfParams): Promise { return this._pdf.generate(options); } diff --git a/packages/playwright-core/src/server/chromium/crPdf.ts b/packages/playwright-core/src/server/chromium/crPdf.ts index 390ea65bf0..5873e1b99d 100644 --- a/packages/playwright-core/src/server/chromium/crPdf.ts +++ b/packages/playwright-core/src/server/chromium/crPdf.ts @@ -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 { + async generate(options: channels.PagePdfParams): Promise { const { scale = 1, displayHeaderFooter = false, diff --git a/packages/playwright-core/src/server/cookieStore.ts b/packages/playwright-core/src/server/cookieStore.ts index 9c7bd2dd38..3be259b9bd 100644 --- a/packages/playwright-core/src/server/cookieStore.ts +++ b/packages/playwright-core/src/server/cookieStore.ts @@ -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> = 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()); diff --git a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts index a34d326133..de4b0b2e85 100644 --- a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts @@ -274,7 +274,7 @@ export class PageDispatcher extends Dispatcher imple async stopJSCoverage(params: channels.PageStopJSCoverageParams, metadata: CallMetadata): Promise { const coverage = this._page.coverage as CRCoverage; - return { entries: await coverage.stopJSCoverage() }; + return await coverage.stopJSCoverage(); } async startCSSCoverage(params: channels.PageStartCSSCoverageParams, metadata: CallMetadata): Promise { @@ -284,7 +284,7 @@ export class PageDispatcher extends Dispatcher imple async stopCSSCoverage(params: channels.PageStopCSSCoverageParams, metadata: CallMetadata): Promise { const coverage = this._page.coverage as CRCoverage; - return { entries: await coverage.stopCSSCoverage() }; + return await coverage.stopCSSCoverage(); } _onFrameAttached(frame: Frame) { diff --git a/packages/playwright-core/src/server/electron/electron.ts b/packages/playwright-core/src/server/electron/electron.ts index 461204fed5..2541f6a186 100644 --- a/packages/playwright-core/src/server/electron/electron.ts +++ b/packages/playwright-core/src/server/electron/electron.ts @@ -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, }; diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index e17ea3484c..66a88ea910 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -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; abstract _defaultOptions(): FetchRequestOptions; - abstract _addCookies(cookies: types.NetworkCookie[]): Promise; - abstract _cookies(url: URL): Promise; + abstract _addCookies(cookies: channels.NetworkCookie[]): Promise; + abstract _cookies(url: URL): Promise; abstract storageState(): Promise; 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 & { fetchUid: string }> { + async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise { 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{ + private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise & { 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((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 { + async _addCookies(cookies: channels.NetworkCookie[]): Promise { await this._context.addCookies(cookies); } - async _cookies(url: URL): Promise { + async _cookies(url: URL): Promise { 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 { + async _addCookies(cookies: channels.NetworkCookie[]): Promise { this._cookieStore.addCookies(cookies); } - async _cookies(url: URL): Promise { + async _cookies(url: URL): Promise { 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: '', diff --git a/packages/playwright-core/src/server/firefox/ffAccessibility.ts b/packages/playwright-core/src/server/firefox/ffAccessibility.ts index 4cd76c1e26..eb7035bb53 100644 --- a/packages/playwright-core/src/server/firefox/ffAccessibility.ts +++ b/packages/playwright-core/src/server/firefox/ffAccessibility.ts @@ -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 = [ + const userStringProperties: Array = [ 'name', 'description', 'roledescription', @@ -215,7 +215,7 @@ class FFAXNode implements accessibility.AXNode { continue; node[userStringProperty] = this._payload[userStringProperty]; } - const booleanProperties: Array = [ + const booleanProperties: Array = [ 'disabled', 'expanded', 'focused', @@ -234,7 +234,7 @@ class FFAXNode implements accessibility.AXNode { continue; node[booleanProperty] = value; } - const numericalProperties: Array = [ + const numericalProperties: Array = [ 'level' ]; for (const numericalProperty of numericalProperties) { @@ -242,7 +242,7 @@ class FFAXNode implements accessibility.AXNode { continue; node[numericalProperty] = this._payload[numericalProperty]; } - const tokenProperties: Array = [ + const tokenProperties: Array = [ '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'; diff --git a/packages/playwright-core/src/server/firefox/ffBrowser.ts b/packages/playwright-core/src/server/firefox/ffBrowser.ts index f257bba366..dedf9d939d 100644 --- a/packages/playwright-core/src/server/firefox/ffBrowser.ts +++ b/packages/playwright-core/src/server/firefox/ffBrowser.ts @@ -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 { + async doCreateNewContext(options: channels.BrowserNewContextParams): Promise { 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 { + async doGetCookies(urls: string[]): Promise { 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, diff --git a/packages/playwright-core/src/server/har/harRecorder.ts b/packages/playwright-core/src/server/har/harRecorder.ts index 6538e59c68..9f75cf1eba 100644 --- a/packages/playwright-core/src/server/har/harRecorder.ts +++ b/packages/playwright-core/src/server/har/harRecorder.ts @@ -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; diff --git a/packages/playwright-core/src/server/network.ts b/packages/playwright-core/src/server/network.ts index 861c7c8e23..ed562df798 100644 --- a/packages/playwright-core/src/server/network.ts +++ b/packages/playwright-core/src/server/network.ts @@ -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'); diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 94a44d0052..74ed9f15b1 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -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; getAccessibilityTree(needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}>; - pdf?: (options?: types.PDFOptions) => Promise; + pdf?: (options: channels.PagePdfParams) => Promise; 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(); - readonly pdf: ((options?: types.PDFOptions) => Promise) | undefined; + readonly pdf: ((options: channels.PagePdfParams) => Promise) | undefined; readonly coverage: any; private _clientRequestInterceptor: network.RouteHandler | undefined; private _serverRequestInterceptor: network.RouteHandler | undefined; diff --git a/packages/playwright-core/src/server/types.ts b/packages/playwright-core/src/server/types.ts index 14a34f4298..b9a1b24fb7 100644 --- a/packages/playwright-core/src/server/types.ts +++ b/packages/playwright-core/src/server/types.ts @@ -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 = new Set(['screen', 'print']); export type ColorScheme = 'dark' | 'light' | 'no-preference'; -export const colorSchemes: Set = new Set(['dark', 'light', 'no-preference']); export type ReducedMotion = 'no-preference' | 'reduce'; -export const reducedMotions: Set = new Set(['no-preference', 'reduce']); export type ForcedColors = 'active' | 'none'; -export const forcedColors: Set = 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, -}; diff --git a/packages/playwright-core/src/server/webkit/wkAccessibility.ts b/packages/playwright-core/src/server/webkit/wkAccessibility.ts index 6c9beea675..447347a08f 100644 --- a/packages/playwright-core/src/server/webkit/wkAccessibility.ts +++ b/packages/playwright-core/src/server/webkit/wkAccessibility.ts @@ -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 = [ + const userStringProperties: Array = [ 'keyshortcuts', 'valuetext' ]; @@ -205,7 +205,7 @@ class WKAXNode implements accessibility.AXNode { (node as any)[userStringProperty] = this._payload[userStringProperty]; } - const booleanProperties: Array = [ + const booleanProperties: Array = [ 'disabled', 'expanded', 'focused', @@ -227,7 +227,7 @@ class WKAXNode implements accessibility.AXNode { (node as any)[booleanProperty] = value; } - const numericalProperties: Array = [ + const numericalProperties: Array = [ '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 = [ + const tokenProperties: Array = [ 'autocomplete', 'haspopup', 'invalid', diff --git a/packages/playwright-core/src/server/webkit/wkBrowser.ts b/packages/playwright-core/src/server/webkit/wkBrowser.ts index 44a0ae971f..d1df3edc59 100644 --- a/packages/playwright-core/src/server/webkit/wkBrowser.ts +++ b/packages/playwright-core/src/server/webkit/wkBrowser.ts @@ -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 { + async doCreateNewContext(options: channels.BrowserNewContextParams): Promise { 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 { + async doGetCookies(urls: string[]): Promise { 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,