Skip to content

feat(browserContext): support maximized viewport - #43363

Open
Devin Rousso (dcrousso) wants to merge 2 commits into
microsoft:mainfrom
dcrousso:fix-1086
Open

Devin Rousso (dcrousso) wants to merge 2 commits into
microsoft:mainfrom
dcrousso:fix-1086

Conversation

@dcrousso

@dcrousso Devin Rousso (dcrousso) commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

allow viewport: 'maximized' to maximize native browser windows without a default emulated viewport

keep native maximization independent of browser fullscreen and the web Fullscreen API

restore and resize the native window when page.setViewportSize() enables viewport emulation

fixes #1086

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Comment thread docs/src/api/params.md Outdated
Use `null` to disable the consistent viewport emulation. Learn more about [viewport emulation](../emulation#viewport).
Use `"maximized"` to disable viewport emulation and maximize each native browser window. This is only supported in headed mode and does not enter fullscreen mode or trigger the web Fullscreen API.

Calling [`method: Page.setViewportSize`] overrides `"maximized"` for that page and resizes its native window.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this sentence is confusing rather than helping.

Comment thread packages/isomorphic/codegen/java.ts Outdated
if (options.userAgent)
lines.push(` .setUserAgent(${quote(options.userAgent)})`);
if (options.viewport)
if (options.viewport && options.viewport !== 'maximized')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why suddenly a java-only change? I'd expect either all languages or none.

Comment thread docs/src/api/params.md
tests non-deterministic.
:::

## java-context-option-viewport

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's sketch out how this API looks for other languages right away.

Comment thread packages/protocol/spec/mixins.yml Outdated
properties:
width: int
height: int
viewportMaximized: boolean?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend an enum viewportMode instead of noDefaultViewport+viewportMaximized. Otherwise it's unclear what noDefaultViewport: true, viewportMaximized: true means.

Comment thread tests/library/headful.spec.ts Outdated
it('should create context in maximized window without entering fullscreen', async ({ browser, browserName }) => {
const context = await browser.newContext({ viewport: 'maximized' });
const page = await context.newPage();
await expect.poll(() => windowIsMaximized(context, page, browserName)).toBe(true);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have to poll here? Shouldn't the newPage already be maximized right away? I'd expect that from the API.

startAutomaticVideoRecording(this._page);
await Promise.all(promises);
if (contextOptions.viewportMaximized) {
await this._browserContext._browser._browserSession.send('Playwright.maximizeWindow', {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Why is this not a part of _updateViewport() method? It seems to be either viewport or maximized, but not both.
  • Similarly, does setting viewport undo Playwright.maximizeWindow? If so, perhaps it should be the same webkit protocol method as well?

Comment thread tests/library/headful.spec.ts Outdated
await context.close();
});

it('should override maximized viewport when resizing a page', async ({ browser, browserName }) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect a symmetric test as well: create a context with viewport=567x345, then call page.setViewportSize('maximized') after.

},
}));
}
if (this._options.viewportMaximized) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like this should be a part of doUpdateDefaultViewport().


async _initialize(hasUIWindow: boolean) {
const browserOptions = this._crPage._browserContext._browser.options;
const options = this._crPage._browserContext._options;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: contextOptions

}));
}
// Make sure that the viewport emulationis set after the embedder window resize.
promises.push(this._client.send('Emulation.setDeviceMetricsOverride', metricsOverride));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect the new "maximized" option to affect metricsOverride somehow...

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🟢 The CI failure is a confirmed pre-existing flake

Hi, I'm the Playwright bot and I checked the latest CI reports. The failure is unlikely to be caused by this PR.

Details

The latest MCP report has one failure; the latest library/test-runner report has none. CI tested PR head afcd11266 as merge commit 3d11b41cf.

Pre-existing flake

  • [chromium] › mcp/sse.spec.ts:196 › sse transport browser lifecycle (persistent) on mcp-ubuntu-latest-chromium — after reconnecting, localStorage.a was undefined instead of "42" in the failed job.
  • The exact same test and assertion failed on main at de4a9068c and on #43781, independently of this PR. In the refreshed results database, this test on the same Ubuntu/Chromium bot passed 726 runs and failed 6 outside this PR, from October 6 through November 2.
  • This PR changes shared viewport setup, but this test uses the default headless viewport, not viewport: 'maximized'. The MCP connection and persistent-profile handling are unchanged. The matching failures elsewhere support a pre-existing flake, not a viewport regression.

Triaged by the Playwright bot - agent run

this._browserContext._browser._browserSession.send('Playwright.maximizeWindow', {
pageProxyId: this._pageProxySession.sessionId,
}),
this._session.send('Page.setScreenSizeOverride', {}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also clear Emulation.setDeviceMetricsOverride?

Comment thread tests/library/headful.spec.ts Outdated
it.skip(({ isBidi }) => isBidi, 'maximized viewport is not supported by BiDi');

async function windowIsMaximized(context: BrowserContext, page: Page, browserName: string) {
if (browserName === 'chromium') {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why use CDP instead of checking outerWidth/outerHeight like in other browsers?


override async doUpdateDefaultViewport() {
if (this._options.viewportMode === 'maximized') {
await this._browser.session.send('Browser.setWindowMaximized', {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we control juggler, I'd prefer to use Browser.setDefaultViewport with "maximized" option, because maximized vs viewport are mutually exclusive. Otherwise, it's unclear what juggler would do if you send both commands. WDYT?

return;
const promises = [];
if (!preserveWindowBoundaries && this._windowId) {
if (options.viewportMode === 'maximized')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to gate this by a local field this._windowState, similar to this._metricsOverride, which would mean "the last set window state".

Comment thread docs/src/api/params.md
Use `viewport="maximized"` to disable viewport emulation and maximize native browser windows. This is only supported in headed mode and does not enter fullscreen mode or trigger the web Fullscreen API.

:::note
The `no_viewport=True` and `viewport="maximized"` values opt out from the default presets and make viewport depend on the host window size defined by the operating system. It makes the execution of the tests non-deterministic.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing these two together shows the non-ideal api 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

i kept the existing no_viewport option for compatibility rather than adding another flag for maximization

are we OK having a breaking change for this or do we need to keep it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to keep it for sure.

Comment thread tests/library/unit/codegen.spec.ts Outdated
import { PythonLanguageGenerator } from '../../../packages/isomorphic/codegen/python';
import { getAPIRequestCodeGen } from '../../../packages/trace-viewer/src/ui/codegen';

test('CG-192 should generate maximized viewport context options', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/1086' } }, () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't say I love this change detector test.

allow `viewport: 'maximized'` to maximize native browser windows without a default emulated viewport

keep native maximization independent of browser fullscreen and the web Fullscreen API

preserve the maximized outer window when `Page.setViewportSize()` enables viewport emulation
`noDefaultViewport` duplicates `viewportMode`

use `viewportMode` as the only viewport mode setting
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Test results for "tests 1"

1 flaky ⚠️ [chromium-library] › library/video.spec.ts:762 › screencast › VI-030 should work with video+trace `@chromium-playwright-x64-ubuntu24-64-core-node22`

23594 passed, 725 skipped


Merge workflow run.

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Test results for "MCP"

5194 passed, 616 skipped


Merge workflow run.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] create context in fullscreen mode

3 participants