diff --git a/package-lock.json b/package-lock.json index 9015275e9b..05efd75c14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "playwright-core", - "version": "0.13.0-post", + "version": "0.14.0-post", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/chromium/crBrowser.ts b/src/chromium/crBrowser.ts index 3b78e79eac..dbe0d0a3bc 100644 --- a/src/chromium/crBrowser.ts +++ b/src/chromium/crBrowser.ts @@ -46,10 +46,11 @@ export class CRBrowser extends BrowserBase { private _tracingRecording = false; private _tracingPath: string | null = ''; private _tracingClient: CRSession | undefined; + readonly _isHeadful: boolean; - static async connect(transport: ConnectionTransport, isPersistent: boolean, logger: InnerLogger, slowMo?: number): Promise { - const connection = new CRConnection(SlowMoTransport.wrap(transport, slowMo), logger); - const browser = new CRBrowser(connection, logger, isPersistent); + static async connect(transport: ConnectionTransport, isPersistent: boolean, logger: InnerLogger, options: { slowMo?: number, headless?: boolean } = {}): Promise { + const connection = new CRConnection(SlowMoTransport.wrap(transport, options.slowMo), logger); + const browser = new CRBrowser(connection, logger, isPersistent, !options.headless); const session = connection.rootSession; if (!isPersistent) { await session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }); @@ -84,13 +85,14 @@ export class CRBrowser extends BrowserBase { return browser; } - constructor(connection: CRConnection, logger: InnerLogger, isPersistent: boolean) { + constructor(connection: CRConnection, logger: InnerLogger, isPersistent: boolean, isHeadful: boolean) { super(logger); this._connection = connection; this._session = this._connection.rootSession; if (isPersistent) this._defaultContext = new CRBrowserContext(this, null, validateBrowserContextOptions({})); + this._isHeadful = isHeadful; this._connection.on(ConnectionEvents.Disconnected, () => { for (const context of this._contexts.values()) context._browserClosed(); @@ -141,7 +143,7 @@ export class CRBrowser extends BrowserBase { assert(!this._serviceWorkers.has(targetInfo.targetId), 'Duplicate target ' + targetInfo.targetId); if (targetInfo.type === 'background_page') { - const backgroundPage = new CRPage(session, targetInfo.targetId, context, null); + const backgroundPage = new CRPage(session, targetInfo.targetId, context, null, false); this._backgroundPages.set(targetInfo.targetId, backgroundPage); backgroundPage.pageOrError().then(() => { context!.emit(Events.CRBrowserContext.BackgroundPage, backgroundPage._page); @@ -151,7 +153,7 @@ export class CRBrowser extends BrowserBase { if (targetInfo.type === 'page') { const opener = targetInfo.openerId ? this._crPages.get(targetInfo.openerId) || null : null; - const crPage = new CRPage(session, targetInfo.targetId, context, opener); + const crPage = new CRPage(session, targetInfo.targetId, context, opener, this._isHeadful); this._crPages.set(targetInfo.targetId, crPage); if (opener && opener._initializedPage) { for (const signalBarrier of opener._initializedPage._frameManager._signalBarriers) diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index 7cf2fd0084..e8b6414066 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -39,6 +39,7 @@ import { ConsoleMessage } from '../console'; import { NotConnectedError } from '../errors'; import { logError } from '../logger'; + const UTILITY_WORLD_NAME = '__playwright_utility_world__'; export class CRPage implements PageDelegate { @@ -55,7 +56,7 @@ export class CRPage implements PageDelegate { private readonly _pagePromise: Promise; _initializedPage: Page | null = null; - constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null) { + constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null, hasUIWindow: boolean) { this._targetId = targetId; this._opener = opener; this.rawKeyboard = new RawKeyboardImpl(client); @@ -67,7 +68,7 @@ export class CRPage implements PageDelegate { this._mainFrameSession = new FrameSession(this, client, targetId); this._sessions.set(targetId, this._mainFrameSession); client.once(CRSessionEvents.Disconnected, () => this._page._didDisconnect()); - this._pagePromise = this._mainFrameSession._initialize().then(() => this._initializedPage = this._page).catch(e => e); + this._pagePromise = this._mainFrameSession._initialize(hasUIWindow).then(() => this._initializedPage = this._page).catch(e => e); } private async _forAllFrameSessions(cb: (frame: FrameSession) => Promise) { @@ -97,7 +98,7 @@ export class CRPage implements PageDelegate { this._page._frameManager.removeChildFramesRecursively(frame); const frameSession = new FrameSession(this, session, targetId); this._sessions.set(targetId, frameSession); - frameSession._initialize().catch(e => e); + frameSession._initialize(false).catch(e => e); } removeFrameSession(targetId: Protocol.Target.TargetID) { @@ -319,6 +320,7 @@ class FrameSession { private _firstNonInitialNavigationCommittedPromise: Promise; private _firstNonInitialNavigationCommittedFulfill = () => {}; private _firstNonInitialNavigationCommittedReject = (e: Error) => {}; + private _windowId: number | undefined; constructor(crPage: CRPage, client: CRSession, targetId: string) { this._client = client; @@ -364,7 +366,11 @@ class FrameSession { ]; } - async _initialize() { + async _initialize(hasUIWindow: boolean) { + if (hasUIWindow) { + const { windowId } = await this._client.send('Browser.getWindowForTarget'); + this._windowId = windowId; + } let lifecycleEventsEnabled: Promise; if (!this._isMainFrame()) this._addSessionListeners(); @@ -696,6 +702,20 @@ class FrameSession { screenOrientation: isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }, }), ]; + if (this._windowId) { + let insets = { width: 24, height: 88 }; + if (process.platform === 'win32') + insets = { width: 16, height: 88 }; + else if (process.platform === 'linux') + insets = { width: 8, height: 85 }; + else if (process.platform === 'darwin') + insets = { width: 2, height: 80 }; + + promises.push(this._client.send('Browser.setWindowBounds', { + windowId: this._windowId, + bounds: { width: viewport.width + insets.width, height: viewport.height + insets.height } + })); + } await Promise.all(promises); } diff --git a/src/server/chromium.ts b/src/server/chromium.ts index 716589969e..88d8762ca0 100644 --- a/src/server/chromium.ts +++ b/src/server/chromium.ts @@ -49,7 +49,7 @@ export class Chromium implements BrowserType { async launch(options: LaunchOptions = {}): Promise { assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead'); const { browserServer, transport, downloadsPath, logger } = await this._launchServer(options, 'local'); - const browser = await CRBrowser.connect(transport!, false, logger, options.slowMo); + const browser = await CRBrowser.connect(transport!, false, logger, options); browser._ownedServer = browserServer; browser._downloadsPath = downloadsPath; return browser; @@ -60,14 +60,10 @@ export class Chromium implements BrowserType { } async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise { - const { - timeout = 30000, - slowMo = 0, - } = options; const { transport, browserServer, logger } = await this._launchServer(options, 'persistent', userDataDir); - const browser = await CRBrowser.connect(transport!, true, logger, slowMo); + const browser = await CRBrowser.connect(transport!, true, logger, options); browser._ownedServer = browserServer; - await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout); + await helper.waitWithTimeout(browser._firstPagePromise, 'first page', options.timeout || 30000); return browser._defaultContext!; } @@ -137,7 +133,7 @@ export class Chromium implements BrowserType { async connect(options: ConnectOptions): Promise { return await WebSocketTransport.connect(options.wsEndpoint, transport => { - return CRBrowser.connect(transport, false, new RootLogger(options.logger), options.slowMo); + return CRBrowser.connect(transport, false, new RootLogger(options.logger), options); }); }