Skip to content

fix(chromium): sync navigator.platform with userAgentData when custom UA is set#39723

Open
manimovassagh wants to merge 1 commit intomicrosoft:mainfrom
manimovassagh:fix-39568
Open

fix(chromium): sync navigator.platform with userAgentData when custom UA is set#39723
manimovassagh wants to merge 1 commit intomicrosoft:mainfrom
manimovassagh:fix-39568

Conversation

@manimovassagh
Copy link
Contributor

@manimovassagh manimovassagh commented Mar 17, 2026

When a custom userAgent is configured (e.g. via device presets like Desktop Chrome),
navigator.platform leaks the host OS instead of matching the emulated user agent:

  • navigator.userAgentData.platform"Windows" (from the preset UA)
  • navigator.platform"MacIntel" (host OS leaked)

Libraries like React Aria check userAgentData.platform first, get "Windows", and
then expect Windows keyboard behavior — breaking tests that use ControlOrMeta.

Fix across all three browsers:

  • Chromium: passes platform parameter in Emulation.setUserAgentOverride, derived from the same UserAgentMetadata already computed for userAgentData
  • Firefox: calls Browser.setPlatformOverride alongside Browser.setUserAgentOverride
  • WebKit: calls Page.overridePlatform alongside Page.overrideUserAgent

A shared navigatorPlatformFromUA() helper in browserContext.ts derives navigator.platform from the UA string for Firefox and WebKit. Chromium uses its own metadata-driven navigatorPlatform() in crPage.ts for higher precision.

When no custom user agent is set, behavior is unchanged across all browsers.

Setting PLAYWRIGHT_NO_UA_PLATFORM=1 disables the new behavior as an opt-out escape hatch.

Fixes #39568

@manimovassagh manimovassagh marked this pull request as ready for review March 17, 2026 09:26
userAgent: options.userAgent || '',
acceptLanguage: options.locale,
userAgentMetadata: calculateUserAgentMetadata(options),
platform: userAgentMetadata ? navigatorPlatform(userAgentMetadata, options.userAgent || '') : undefined,
Copy link
Member

Choose a reason for hiding this comment

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

Since this change is potentially breaking, please introduce env variable PLAYWRIGHT_NO_UA_PLATFORM that opts in from this behavior. That way we can recommend it to those affected.

While you are here, please explore the feasibility of this fix for WebKit and Firefox.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to confirm — should PLAYWRIGHT_NO_UA_PLATFORM enable the platform override (opt-in, off by default), or disable it (opt-out, on by default)? Happy to flip the logic either way.

@manimovassagh
Copy link
Contributor Author

Updated the PR with both changes:

1. PLAYWRIGHT_NO_UA_PLATFORM env variable
The platform override is active by default. Setting PLAYWRIGHT_NO_UA_PLATFORM=1 disables it, reverting to the previous behavior where navigator.platform reflects the host OS.

2. Firefox and WebKit support
Both browsers already had the protocol commands but weren't using them:

  • Firefox: Browser.setPlatformOverride
  • WebKit: Page.overridePlatform

Added a shared navigatorPlatformFromUA() helper in browserContext.ts that derives navigator.platform from the user agent string. All three browsers now use it when a custom userAgent is set.

Tested locally on Chromium, Firefox, and WebKit — all passing.

@manimovassagh manimovassagh force-pushed the fix-39568 branch 2 times, most recently from 7945185 to b01c399 Compare March 17, 2026 19:05
… all browsers

When a custom userAgent is configured (e.g. via device presets), Playwright
sends platform metadata via CDP/protocol but does not override navigator.platform.
This causes navigator.platform to leak the host OS while the emulated platform
reflects the user agent string.

Pass the platform parameter in Emulation.setUserAgentOverride (Chromium),
Browser.setPlatformOverride (Firefox), and Page.overridePlatform (WebKit).

The new behavior can be disabled by setting PLAYWRIGHT_NO_UA_PLATFORM=1.

Fixes microsoft#39568
@github-actions
Copy link
Contributor

Test results for "MCP"

2 failed
❌ [chrome] › mcp/autowait.spec.ts:19 › racy navigation destroys context @mcp-windows-latest
❌ [chrome] › mcp/cli-session.spec.ts:176 › list --all lists sessions from all workspaces @mcp-windows-latest

5337 passed, 186 skipped


Merge workflow run.

@github-actions
Copy link
Contributor

Test results for "tests 1"

2 failed
❌ [webkit-page] › page/page-basic.spec.ts:88 › page.title should not throw during navigation @webkit-ubuntu-22.04-node20
❌ [playwright-test] › ui-mode-test-network-tab.spec.ts:397 › should not preserve selection across test runs @macos-latest-node20

5 flaky ⚠️ [chromium-page] › page/page-request-continue.spec.ts:754 › propagate headers cross origin redirect after interception `@ubuntu-22.04-chromium-tip-of-tree`
⚠️ [chromium-library] › library/video.spec.ts:358 › screencast › should capture navigation `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/trace-viewer.spec.ts:1223 › should display language-specific locators `@chromium-ubuntu-22.04-node22`
⚠️ [firefox-library] › library/inspector/cli-codegen-1.spec.ts:1080 › cli codegen › should not throw csp directive violation errors `@firefox-ubuntu-22.04-node20`
⚠️ [webkit-library] › library/browsertype-connect.spec.ts:758 › run-server › should upload a folder `@webkit-ubuntu-22.04-node20`

38776 passed, 845 skipped


Merge workflow run.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: navigator.userAgentData returns Windows on Mac. Incompatible with @react-ara/utils isAppleDevice

2 participants