diff --git a/packages/playwright-core/src/client/localUtils.ts b/packages/playwright-core/src/client/localUtils.ts index 3e1e627761..6cadb00326 100644 --- a/packages/playwright-core/src/client/localUtils.ts +++ b/packages/playwright-core/src/client/localUtils.ts @@ -16,9 +16,25 @@ import type * as channels from '@protocol/channels'; import { ChannelOwner } from './channelOwner'; +import type { Size } from './types'; + +type DeviceDescriptor = { + userAgent: string, + viewport: Size, + deviceScaleFactor: number, + isMobile: boolean, + hasTouch: boolean, + defaultBrowserType: 'chromium' | 'firefox' | 'webkit' +}; +type Devices = { [name: string]: DeviceDescriptor }; export class LocalUtils extends ChannelOwner { + readonly devices: Devices; + constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.LocalUtilsInitializer) { super(parent, type, guid, initializer); + this.devices = {}; + for (const { name, descriptor } of initializer.deviceDescriptors) + this.devices[name] = descriptor; } } diff --git a/packages/playwright-core/src/client/playwright.ts b/packages/playwright-core/src/client/playwright.ts index 8f55c19e7b..0dd6e03cb2 100644 --- a/packages/playwright-core/src/client/playwright.ts +++ b/packages/playwright-core/src/client/playwright.ts @@ -22,17 +22,6 @@ import { ChannelOwner } from './channelOwner'; import { Electron } from './electron'; import { APIRequest } from './fetch'; import { Selectors, SelectorsOwner } from './selectors'; -import type { Size } from './types'; - -type DeviceDescriptor = { - userAgent: string, - viewport: Size, - deviceScaleFactor: number, - isMobile: boolean, - hasTouch: boolean, - defaultBrowserType: 'chromium' | 'firefox' | 'webkit' -}; -type Devices = { [name: string]: DeviceDescriptor }; export class Playwright extends ChannelOwner { readonly _android: Android; @@ -40,7 +29,7 @@ export class Playwright extends ChannelOwner { readonly chromium: BrowserType; readonly firefox: BrowserType; readonly webkit: BrowserType; - readonly devices: Devices; + readonly devices: any; selectors: Selectors; readonly request: APIRequest; readonly errors: { TimeoutError: typeof TimeoutError }; @@ -56,9 +45,7 @@ export class Playwright extends ChannelOwner { this.webkit._playwright = this; this._android = Android.from(initializer.android); this._electron = Electron.from(initializer.electron); - this.devices = {}; - for (const { name, descriptor } of initializer.deviceDescriptors) - this.devices[name] = descriptor; + this.devices = this._connection.localUtils()?.devices ?? {}; this.selectors = new Selectors(); this.errors = { TimeoutError }; diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 990e793cc8..c09e609ea6 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -217,7 +217,26 @@ scheme.APIResponse = tObject({ headers: tArray(tType('NameValue')), }); scheme.LifecycleEvent = tEnum(['load', 'domcontentloaded', 'networkidle', 'commit']); -scheme.LocalUtilsInitializer = tOptional(tObject({})); +scheme.LocalUtilsInitializer = tObject({ + deviceDescriptors: tArray(tObject({ + name: tString, + descriptor: tObject({ + userAgent: tString, + viewport: tObject({ + width: tNumber, + height: tNumber, + }), + screen: tOptional(tObject({ + width: tNumber, + height: tNumber, + })), + deviceScaleFactor: tNumber, + isMobile: tBoolean, + hasTouch: tBoolean, + defaultBrowserType: tEnum(['chromium', 'firefox', 'webkit']), + }), + })), +}); scheme.LocalUtilsZipParams = tObject({ zipFile: tString, entries: tArray(tType('NameValue')), @@ -298,25 +317,7 @@ scheme.PlaywrightInitializer = tObject({ webkit: tChannel(['BrowserType']), android: tChannel(['Android']), electron: tChannel(['Electron']), - utils: tChannel(['LocalUtils']), - deviceDescriptors: tArray(tObject({ - name: tString, - descriptor: tObject({ - userAgent: tString, - viewport: tObject({ - width: tNumber, - height: tNumber, - }), - screen: tOptional(tObject({ - width: tNumber, - height: tNumber, - })), - deviceScaleFactor: tNumber, - isMobile: tBoolean, - hasTouch: tBoolean, - defaultBrowserType: tEnum(['chromium', 'firefox', 'webkit']), - }), - })), + utils: tOptional(tChannel(['LocalUtils'])), selectors: tChannel(['Selectors']), preLaunchedBrowser: tOptional(tChannel(['Browser'])), preConnectedAndroidDevice: tOptional(tChannel(['AndroidDevice'])), diff --git a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts index 42c73f2d95..16b863707b 100644 --- a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts @@ -26,7 +26,7 @@ import { Dispatcher } from './dispatcher'; import { yazl, yauzl } from '../../zipBundle'; import { ZipFile } from '../../utils/zipFile'; import type * as har from '@trace/har'; -import type { HeadersArray } from '../types'; +import type { HeadersArray, Devices } from '../types'; import { JsonPipeDispatcher } from '../dispatchers/jsonPipeDispatcher'; import { WebSocketTransport } from '../transport'; import { SocksInterceptor } from '../socksInterceptor'; @@ -53,7 +53,12 @@ export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels. constructor(scope: RootDispatcher, playwright: Playwright) { const localUtils = new SdkObject(playwright, 'localUtils', 'localUtils'); - super(scope, localUtils, 'LocalUtils', {}); + const descriptors = require('../deviceDescriptors') as Devices; + const deviceDescriptors = Object.entries(descriptors) + .map(([name, descriptor]) => ({ name, descriptor })); + super(scope, localUtils, 'LocalUtils', { + deviceDescriptors, + }); this._type_LocalUtils = true; } diff --git a/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts b/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts index 55cf4fb9cb..2122f064c9 100644 --- a/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts @@ -20,7 +20,6 @@ import { GlobalAPIRequestContext } from '../fetch'; import type { Playwright } from '../playwright'; import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../../common/socksProxy'; import { SocksProxy } from '../../common/socksProxy'; -import type * as types from '../types'; import { AndroidDispatcher } from './androidDispatcher'; import { BrowserTypeDispatcher } from './browserTypeDispatcher'; import type { RootDispatcher } from './dispatcher'; @@ -40,9 +39,6 @@ export class PlaywrightDispatcher extends Dispatcher ({ name, descriptor })); const browserDispatcher = preLaunchedBrowser ? new ConnectedBrowserDispatcher(scope, preLaunchedBrowser) : undefined; const android = new AndroidDispatcher(scope, playwright.android); const prelaunchedAndroidDeviceDispatcher = prelaunchedAndroidDevice ? new AndroidDeviceDispatcher(android, prelaunchedAndroidDevice) : undefined; @@ -52,8 +48,7 @@ export class PlaywrightDispatcher extends Dispatcher