Skip to content

Commit 2fcc2b5

Browse files
authored
chore(chromium): resize browser frame when emulating viewport (#1924)
1 parent fa59372 commit 2fcc2b5

File tree

4 files changed

+37
-19
lines changed

4 files changed

+37
-19
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/chromium/crBrowser.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ export class CRBrowser extends BrowserBase {
4646
private _tracingRecording = false;
4747
private _tracingPath: string | null = '';
4848
private _tracingClient: CRSession | undefined;
49+
readonly _isHeadful: boolean;
4950

50-
static async connect(transport: ConnectionTransport, isPersistent: boolean, logger: InnerLogger, slowMo?: number): Promise<CRBrowser> {
51-
const connection = new CRConnection(SlowMoTransport.wrap(transport, slowMo), logger);
52-
const browser = new CRBrowser(connection, logger, isPersistent);
51+
static async connect(transport: ConnectionTransport, isPersistent: boolean, logger: InnerLogger, options: { slowMo?: number, headless?: boolean } = {}): Promise<CRBrowser> {
52+
const connection = new CRConnection(SlowMoTransport.wrap(transport, options.slowMo), logger);
53+
const browser = new CRBrowser(connection, logger, isPersistent, !options.headless);
5354
const session = connection.rootSession;
5455
if (!isPersistent) {
5556
await session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true });
@@ -84,13 +85,14 @@ export class CRBrowser extends BrowserBase {
8485
return browser;
8586
}
8687

87-
constructor(connection: CRConnection, logger: InnerLogger, isPersistent: boolean) {
88+
constructor(connection: CRConnection, logger: InnerLogger, isPersistent: boolean, isHeadful: boolean) {
8889
super(logger);
8990
this._connection = connection;
9091
this._session = this._connection.rootSession;
9192

9293
if (isPersistent)
9394
this._defaultContext = new CRBrowserContext(this, null, validateBrowserContextOptions({}));
95+
this._isHeadful = isHeadful;
9496
this._connection.on(ConnectionEvents.Disconnected, () => {
9597
for (const context of this._contexts.values())
9698
context._browserClosed();
@@ -141,7 +143,7 @@ export class CRBrowser extends BrowserBase {
141143
assert(!this._serviceWorkers.has(targetInfo.targetId), 'Duplicate target ' + targetInfo.targetId);
142144

143145
if (targetInfo.type === 'background_page') {
144-
const backgroundPage = new CRPage(session, targetInfo.targetId, context, null);
146+
const backgroundPage = new CRPage(session, targetInfo.targetId, context, null, false);
145147
this._backgroundPages.set(targetInfo.targetId, backgroundPage);
146148
backgroundPage.pageOrError().then(() => {
147149
context!.emit(Events.CRBrowserContext.BackgroundPage, backgroundPage._page);
@@ -151,7 +153,7 @@ export class CRBrowser extends BrowserBase {
151153

152154
if (targetInfo.type === 'page') {
153155
const opener = targetInfo.openerId ? this._crPages.get(targetInfo.openerId) || null : null;
154-
const crPage = new CRPage(session, targetInfo.targetId, context, opener);
156+
const crPage = new CRPage(session, targetInfo.targetId, context, opener, this._isHeadful);
155157
this._crPages.set(targetInfo.targetId, crPage);
156158
if (opener && opener._initializedPage) {
157159
for (const signalBarrier of opener._initializedPage._frameManager._signalBarriers)

src/chromium/crPage.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { ConsoleMessage } from '../console';
3939
import { NotConnectedError } from '../errors';
4040
import { logError } from '../logger';
4141

42+
4243
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
4344

4445
export class CRPage implements PageDelegate {
@@ -55,7 +56,7 @@ export class CRPage implements PageDelegate {
5556
private readonly _pagePromise: Promise<Page | Error>;
5657
_initializedPage: Page | null = null;
5758

58-
constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null) {
59+
constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null, hasUIWindow: boolean) {
5960
this._targetId = targetId;
6061
this._opener = opener;
6162
this.rawKeyboard = new RawKeyboardImpl(client);
@@ -67,7 +68,7 @@ export class CRPage implements PageDelegate {
6768
this._mainFrameSession = new FrameSession(this, client, targetId);
6869
this._sessions.set(targetId, this._mainFrameSession);
6970
client.once(CRSessionEvents.Disconnected, () => this._page._didDisconnect());
70-
this._pagePromise = this._mainFrameSession._initialize().then(() => this._initializedPage = this._page).catch(e => e);
71+
this._pagePromise = this._mainFrameSession._initialize(hasUIWindow).then(() => this._initializedPage = this._page).catch(e => e);
7172
}
7273

7374
private async _forAllFrameSessions(cb: (frame: FrameSession) => Promise<any>) {
@@ -97,7 +98,7 @@ export class CRPage implements PageDelegate {
9798
this._page._frameManager.removeChildFramesRecursively(frame);
9899
const frameSession = new FrameSession(this, session, targetId);
99100
this._sessions.set(targetId, frameSession);
100-
frameSession._initialize().catch(e => e);
101+
frameSession._initialize(false).catch(e => e);
101102
}
102103

103104
removeFrameSession(targetId: Protocol.Target.TargetID) {
@@ -319,6 +320,7 @@ class FrameSession {
319320
private _firstNonInitialNavigationCommittedPromise: Promise<void>;
320321
private _firstNonInitialNavigationCommittedFulfill = () => {};
321322
private _firstNonInitialNavigationCommittedReject = (e: Error) => {};
323+
private _windowId: number | undefined;
322324

323325
constructor(crPage: CRPage, client: CRSession, targetId: string) {
324326
this._client = client;
@@ -364,7 +366,11 @@ class FrameSession {
364366
];
365367
}
366368

367-
async _initialize() {
369+
async _initialize(hasUIWindow: boolean) {
370+
if (hasUIWindow) {
371+
const { windowId } = await this._client.send('Browser.getWindowForTarget');
372+
this._windowId = windowId;
373+
}
368374
let lifecycleEventsEnabled: Promise<any>;
369375
if (!this._isMainFrame())
370376
this._addSessionListeners();
@@ -696,6 +702,20 @@ class FrameSession {
696702
screenOrientation: isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' },
697703
}),
698704
];
705+
if (this._windowId) {
706+
let insets = { width: 24, height: 88 };
707+
if (process.platform === 'win32')
708+
insets = { width: 16, height: 88 };
709+
else if (process.platform === 'linux')
710+
insets = { width: 8, height: 85 };
711+
else if (process.platform === 'darwin')
712+
insets = { width: 2, height: 80 };
713+
714+
promises.push(this._client.send('Browser.setWindowBounds', {
715+
windowId: this._windowId,
716+
bounds: { width: viewport.width + insets.width, height: viewport.height + insets.height }
717+
}));
718+
}
699719
await Promise.all(promises);
700720
}
701721

src/server/chromium.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Chromium implements BrowserType<CRBrowser> {
4949
async launch(options: LaunchOptions = {}): Promise<CRBrowser> {
5050
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
5151
const { browserServer, transport, downloadsPath, logger } = await this._launchServer(options, 'local');
52-
const browser = await CRBrowser.connect(transport!, false, logger, options.slowMo);
52+
const browser = await CRBrowser.connect(transport!, false, logger, options);
5353
browser._ownedServer = browserServer;
5454
browser._downloadsPath = downloadsPath;
5555
return browser;
@@ -60,14 +60,10 @@ export class Chromium implements BrowserType<CRBrowser> {
6060
}
6161

6262
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
63-
const {
64-
timeout = 30000,
65-
slowMo = 0,
66-
} = options;
6763
const { transport, browserServer, logger } = await this._launchServer(options, 'persistent', userDataDir);
68-
const browser = await CRBrowser.connect(transport!, true, logger, slowMo);
64+
const browser = await CRBrowser.connect(transport!, true, logger, options);
6965
browser._ownedServer = browserServer;
70-
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
66+
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', options.timeout || 30000);
7167
return browser._defaultContext!;
7268
}
7369

@@ -137,7 +133,7 @@ export class Chromium implements BrowserType<CRBrowser> {
137133

138134
async connect(options: ConnectOptions): Promise<CRBrowser> {
139135
return await WebSocketTransport.connect(options.wsEndpoint, transport => {
140-
return CRBrowser.connect(transport, false, new RootLogger(options.logger), options.slowMo);
136+
return CRBrowser.connect(transport, false, new RootLogger(options.logger), options);
141137
});
142138
}
143139

0 commit comments

Comments
 (0)