Skip to content

fix(emulation): sync navigator.platform with custom user agent across all browsers#39723

Open
manimovassagh wants to merge 4 commits intomicrosoft:mainfrom
manimovassagh:fix-39568
Open

fix(emulation): sync navigator.platform with custom user agent across all browsers#39723
manimovassagh wants to merge 4 commits 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.

Changes

Per @dgozman's request, unified into a single calculateUserAgentEmulation(options: BrowserContextOptions) in browserContext.ts that returns:

  • navigatorPlatform: string | undefined
  • userAgentMetadata: { mobile, model, architecture, platform, platformVersion } | undefined

The PLAYWRIGHT_NO_UA_PLATFORM check lives inside this function (not duplicated across call sites).

Chromium (crPage.ts): passes platform in Emulation.setUserAgentOverride via userAgentMetadata
Firefox (ffBrowser.ts): calls Browser.setPlatformOverride alongside Browser.setUserAgentOverride
WebKit (wkPage.ts): calls Page.overridePlatform alongside Page.overrideUserAgent

platformVersion is normalized: UA strings encode iOS/macOS versions with underscores (16_6) but Client Hints expect dots (16.6).

When no custom user agent is set, behavior is unchanged. Set PLAYWRIGHT_NO_UA_PLATFORM=1 to opt out.

Fixes #39568

@manimovassagh manimovassagh marked this pull request as ready for review March 17, 2026 09:26
@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

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Test results for "MCP"

1 failed
❌ [webkit] › mcp/dashboard.spec.ts:45 › should pick locator from browser @mcp-macos-latest

5338 passed, 186 skipped


Merge workflow run.

@github-actions
Copy link
Contributor

Test results for "tests 1"

2 failed
❌ [playwright-test] › expect.spec.ts:964 › should support mergeExpects @macos-latest-node20
❌ [playwright-test] › loader.spec.ts:758 › should resolve .js import to .tsx file in non-ESM mode for components @macos-latest-node20

6 flaky ⚠️ [chromium-library] › library/trace-viewer.spec.ts:1223 › should display language-specific locators `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/trace-viewer.spec.ts:1223 › should display language-specific locators `@chromium-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/trace-viewer.spec.ts:1223 › should display language-specific locators `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-page] › page/page-network-idle.spec.ts:141 › should wait for networkidle from the popup `@firefox-ubuntu-22.04-node20`
⚠️ [playwright-test] › ui-mode-test-output.spec.ts:118 › should collapse repeated console messages for test `@macos-latest-node20`
⚠️ [playwright-test] › ui-mode-trace.spec.ts:185 › should show snapshots for steps `@windows-latest-node20`

38806 passed, 845 skipped


Merge workflow run.

…ion in browserContext

Consolidates calculateUserAgentMetadata (crPage.ts) and navigatorPlatformFromUA
(browserContext.ts) into a single calculateUserAgentEmulation() exported from
browserContext.ts. All three browsers now call this one function which also
handles the PLAYWRIGHT_NO_UA_PLATFORM check internally.

Removes the duplicated env-var checks from crPage.ts, ffBrowser.ts, and wkPage.ts.
…acOS

UA strings encode version as e.g. "iPhone OS 16_6" but Chromium Client
Hints platformVersion expects "16.6". Apply replace(/_/g, '.') for iOS
and macOS matches.
@manimovassagh manimovassagh changed the title fix(chromium): sync navigator.platform with userAgentData when custom UA is set fix(emulation): sync navigator.platform with custom user agent across all browsers Mar 24, 2026
@manimovassagh manimovassagh requested a review from dgozman March 24, 2026 14:02
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

3 participants