Skip to content

fix(emulate): scope remembered overrides to the session and attachment - #352

Merged
iuyo5678 merged 1 commit into
Tencent:mainfrom
NianJiuZst:codex/fix-emulation-lifecycle
Sep 27, 2026
Merged

iuyo5678 merged 1 commit into
Tencent:mainfrom
NianJiuZst:codex/fix-emulation-lifecycle

Conversation

@NianJiuZst

@NianJiuZst NianJiuZst commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

After session A returns a tab, Chrome's debugger detach clears its emulation overrides. A later session B that sets only width and height can nevertheless restore A's user agent, touch settings, mobile flag and DPR, because the extension remembers those fields in a global map keyed only by tab ID.

Scope remembered overrides to the session context and the CDP runner/attachment that applied them. Preserve partial updates within the same live context. Fixes #350.

Reproduction and evidence

Failing base: 8cbcc490. Validated PR head: 67629e81.

The emulation-lifecycle.browser.test.ts performs this sequence on a surviving Chrome tab:

  1. Session A applies 390 × 844, DPR 3, mobile: true, user agent BSK-AUDIT-OLD-SESSION, and touch with 5 points.
  2. Call production releaseSessionTab, then stop A. The debugger is actually detached; a subsequent read reattaches and confirms the original desktop UA and zero touch points.
  3. Start session B and request only width: 1200, height: 800.
  4. Inspect both the handler response and navigator.userAgent / navigator.maxTouchPoints.
Stage Base observation Observation with this PR
After A's emulation Custom UA, touch 5 Custom UA, touch 5
After returning A's tab Original desktop UA, touch 0 Original desktop UA, touch 0
After B's viewport-only request Old custom UA and touch 5 return; response also contains DPR 3 and mobile: true Original desktop UA and touch 0 remain; applied request contains only the new dimensions

The browser regression failed on the base and passed on this PR. The unit tests additionally isolate owner and attachment changes, rather than relying only on a scenario that changes both at once.

Implementation

The remembered state is now a WeakMap<SessionContext, Map<tabId, EmulationState>>. Each entry records the CDP runner, attachment ID, and fully applied overrides.

  • A new SessionContext starts without the previous owner's remembered fields, even if the session ID string is reused.
  • Before merging, the handler requires the same CDP runner and attachment ID. A detached or replaced attachment does not reuse the old profile.
  • The attachment ID is recorded after applying overrides, because the first emulation call can itself establish the attachment.
  • Same-session, same-attachment requests still merge partial fields; a successful off clears that context's remembered entry.
  • State is recorded only after all requested overrides finish successfully, preserving the existing partial-failure/no-rollback behavior.

This changes cache ownership and validation at the next merge. It relies on the existing debugger detach path to reset Chrome's actual overrides; it does not introduce new tab-return or session-stop hooks.

Validation

Local environment: macOS, Node 26.10.0, pnpm 10.17.0, Vitest 4.1.6, Chrome 153.0.8010.54.

Suite / check Result and coverage
emulate.test.ts 32 tests passed; includes 6 new cases covering another session, a reused session ID, detach, reattach, runner replacement, and partial updates after first-call attachment
emulation-lifecycle.browser.test.ts 1 test passed with native Chrome emulation and detach/reattach
TypeScript compile, changed-file Biome, git diff --check Passed

Local focused total: 33 passed.

Use the repository's declared pnpm 10.17.0, from the repository root. The local runs used npm exec --yes --package pnpm@10.17.0 -- pnpm ... to select that version. Set BSK_CLICK_CHROME to an installed Chrome executable; without it the browser test is skipped.

pnpm install --frozen-lockfile
pnpm --filter @browser-skill/extension exec wxt prepare
BSK_CLICK_CHROME=/path/to/chrome \
  pnpm --filter @browser-skill/extension exec vitest run \
  src/tools/__tests__/emulate.test.ts \
  src/tools/__tests__/emulation-lifecycle.browser.test.ts
pnpm --filter @browser-skill/extension compile

Hosted CI: one failure remains

For 67629e81, checked 2026-09-26 UTC, 7 checks passed and 1 failed. Frontend lint/typecheck/tests/build, Rust, all Windows jobs, Node scripts and CodeCC passed.

The browser CI job failed in unchanged network-control.browser.test.ts:

Expected recorded request body: { keep: 1, name: '张三' }
Received recorded request body: { displayName: '张三', keep: 1 }

GitHub marks the subsequent Run emulation-lifecycle browser regression step as skipped. Accordingly, this PR's new browser regression is locally verified, but it did not run in that hosted attempt.

The failing network test and the new emulation browser test passed together in a local follow-up run (2/2):

BSK_CLICK_CHROME=/path/to/chrome \
  pnpm --filter @browser-skill/extension exec vitest run \
  src/debug/__tests__/network-control.browser.test.ts \
  src/tools/__tests__/emulation-lifecycle.browser.test.ts

No debug/CDP implementation or existing network browser test is changed by this PR. The cause of that hosted failure has not been established; the local pass is not a substitute for the failed hosted check. GitHub denied the rerun request with Must have admin rights to Repository, so a maintainer rerun or investigation is still needed.

Verification boundary

The browser test executes production ChromiumCdp, handleEmulate, and releaseSessionTab against real Chrome. Window creation, tab ownership metadata, and session window removal are adapted by the harness. It does not drive the extension's tab-borrow/return UI or the complete CLI/daemon transport. DPR/mobile defaults and merge isolation are also checked at the handler/CDP-call level in unit tests.

@iuyo5678
iuyo5678 merged commit 4061767 into Tencent:main Sep 27, 2026
14 of 15 checks passed
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] Viewport-only emulation restores a previous session's user agent and touch settings

2 participants