Repository navigation
feat: add native browser profile targeting across MCP and Claw - #2908
Merged
Merged
Conversation
Re-admit bound pages after advisory settling and dialog races before reading shared dialog state. Add a disposable protocol regression proving denied readbacks retain the signal without disclosing its text.
Check the actual eligible group window before applying inherited creation defaults in scripts and granular tools. Keep explicit conflicts in core admission and cover alternate working-window placement and moved defaults against the real guard.
Implement the approved CdpConnection epoch methods with generation checks and dispatch publication under one fixture lock. Cover decoded and raw futures prepared before reconnect without recording or mutating the replacement fixture. Validation awaits the published core trait addition; current errors are the exact missing epoch members.
Contributor
✅ Tests passed: 3381/3384Ran 16 of 16 suites (0 not affected by this change).
|
Automated release snapshot update.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Automated release snapshot update.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
A delayed callback can move the last page out of an explicit group and delete the ID returned by a successful create. Order group mutations with conversation grouping in granular calls and script tool dispatch, and refresh membership through the captured creation view after lookup. Cover update/close in both orders and real run dispatch, external placement, queued client cancellation and operator Stop, and read-only progress. Validation: 672 Claw tests and Rustdoc pass; strict all-target Clippy and owned formatting pass with private Cargo build and target directories.
An acknowledged rebind advances selection revision but must reuse a live native group in the same conversation, saved profile and actual window. Remove revision from the private placement key while retaining captured BrowserView/creation guards and the lookup signature. Cover both scope revisits and a late older-revision callback with a full global inventory assertion. Correct the existing generation expectation to match the frozen contract; keep distinct destination assertions. Validation: 673 Claw tests and Rustdoc, strict all-target Clippy and owned formatting pass using private Cargo build and target directories.
Extract the reviewed and chrome-built native range 5d203e252e72d9cc01e6871d2d21f303a3594a35..8e837bd21d767ac7a4833fdf7e56e3efe9186933 as eight cumulative BASE_COMMIT patches. Register their dedicated renderer-termination-diagnostics owner. All eight patches byte-match and apply to the canonical base. Existing store bodies, ownership, Rust tree, and protocol bytes remain unchanged.
Nikhil (shadowfax92)
marked this pull request as ready for review
October 13, 2026 17:29
Contributor
|
Capture the current CSS viewport at native device density when size is omitted. Constrain only supplied size axes and retain the existing full-page path.
Remove the eight added renderer-termination diagnostic patches and only their dedicated feature ownership. The complete BrowserOS tree returns to profile-only 49576; Rust, protocol bytes and all 394 existing store bodies remain unchanged. Native removal 289b233ea9b93e49f1452ebdb6ac27db0b70b2c7 restores the complete reviewed 5d tree, passed the single independent source review and a fresh exact chrome build. Reduced extraction is idempotent; all 17 profile patches MATCH/APPLIES, and all eight removed paths have empty cumulative BASE diffs and no owner.
LoadExistingProfileByPath now creates and registers the existing-only
Profile itself and joins through the stock CreateProfileAsync, so the
public CreateProfileAsync signature, its deferral rebinds, creation
branch and the CreateMultiProfileAsync call site return to upstream.
profile_manager.{cc,h} become pure insertions.
Profile::CreateProfile keeps upstream's switch: the existing-only
preflight precedes it, the asynchronous case skips directory creation
and the synchronous case refuses to create a directory that vanished
after the preflight. Upstream's profile.h comment and OnPrefsLoaded
formatting are restored.
Strict existing-only loading, the prefs-status check, the Windows
cache guard and first-loader versus joiner reporting are unchanged.
Cumulative patches extracted from native task commit 70a7f70a
(built with the chrome gate and independently reviewed).
Integrate main b1c9bb1 (viewport-native screenshot default with optional size axes) with the profile-target branch 31ab08d (captured BrowserView guards). - screenshot.rs: keep the bound view's guarded page session for Page.getLayoutMetrics and pass main's optional size. ToolCtx no longer exposes the raw registry session, so main's unrestricted lookup cannot return. - tests.rs: main's invalid-size test now uses an existing harness page. Central dispatch admits the primary page before a handler validates its arguments; the test still asserts that no Page or Emulation call follows.
Main's default viewport clip adds Page.getLayoutMetrics before capture. Exercise it through a profile-bound BrowserView: both calls use the admitted page session, an out-of-scope page is never measured or captured, and a target replaced during measurement fails before capture.
Nikhil (shadowfax92)
added a commit
that referenced
this pull request
Oct 14, 2026
Add platform, macOS architecture and draft-only publication choices to the full Neo release workflow, preserving all/universal/alpha defaults. Retain exact-source component drafts without public feeds, latest aliases or notifications; finalize only selected browser assets. Deferred component attachments fail closed before public mutation. Advance only BROWSEROS_PATCH from 2 to 3 after profile PR #2908. Native profile patches and the full agent/Rust tree are unchanged. Validation: one independent workflow review and vetted fixes; 1270 bos_build tests (two existing skips), 66 TypeScript release tests, Ruff/actionlint, and exact-head GitHub Tests and Build System Tests passed. This prepares a macOS arm64 GitHub draft test build; it does not claim a built or runtime-verified artifact. TKT-1025 findings and the accepted removal-race limitation remain unfixed.
Nikhil (shadowfax92)
added a commit
that referenced
this pull request
Oct 14, 2026
) * feat(claw): gate native profile features on the BrowserOS version claw-server ships by OTA ahead of the native browser, so a new server can drive a browser that predates PR #2908's profile bundle. Add one native capability table in browseros-core (ProfileTargeting needs BrowserOS 0.51.1.3) keyed on the browser's own instance.browseros_version from the launch config, read leniently: missing, blank or malformed identity is unknown and supports no gated feature. - Hide browser_profiles/browser_target, the profile instructions, run's profile docs and its browser.profiles/browser.target exports when unsupported. - Refuse tagged tools centrally in execute_tool (cached lists, direct calls, run tool:*), and table-listed raw CDP methods and (method, param) pairs, before the gated operation is sent. Stock browserContextId uses stay allowed. - Run a saved binding unbound on an unsupported native, keep it persisted, and add one note to the outer result. Supported capture and live identity checks are unchanged. - CLAW_NATIVE_BROWSEROS_VERSION is a logged developer assertion; dev/dogfood sidecars record only a signed bundle's 10000.-prefixed CFBundleVersion. * fix(claw): gate typed tab creation with a context; clarify dev stamp trust Review follow-up. BrowserView::new_page now requires profile targeting before sending createTab with an explicit browserContextId, matching the raw guard; creation without a context is unchanged. The dev/dogfood writers trust the release pipeline's 10000.-prefixed CFBundleVersion stamp, not a verified signature; say so plainly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A task can select an existing regular browser profile once and retain that selection across tools, JavaScript runs and legitimate Claw session successors. Each request captures its binding and connection epoch; rebinding affects later requests. Unbound calls keep their existing behavior.
browser_profilessupportslistandload.browser_targetsupportsget,set,set_window,clear_windowandclear; window CRUD stays separate. Saved profile handles are distinct from genuine live CDP contexts and Claw agent profiles. Unknown or missing profiles are not created implicitly. Working windows control placement; strict pins restrict access and fail when closed.Claw retains intent through aliases and successors and requires explicit reselection after native handles expire. Groups are reused per conversation, saved profile and actual normal window. Explicit and deferred grouping share the operation guard through native readback. Clearing selection does not close borrowed windows or delete profiles.
Bound access includes normal windows only. OAuth and
window.openpopups returnpage_out_of_scopewhile bound; explicitly clear selection to drive them. UI implementation is deferred.Current-main integration
Head
23e9be1f19858498757b4c4b1e47970b134412d2contains both mainb1c9bb10and profile head31ab08d5without rewriting history. The sole textual conflict was inscreenshot.rs: it retains main's uncapped native-density viewport and optional size axes while using the capturedBrowserViewfor both metrics and capture. A regression proves out-of-scope refusal and rejection of target replacement during metrics before any capture. Its mutation check fails when the guarded page session is bypassed.Local verification: 1,061 Rust workspace tests, strict all-target Clippy, formatting, TypeScript checks, and 43 screenshot/register checks passed. The invalid-size fixture now admits an existing page before asserting that no page protocol call is made, preserving central admission order. All 17 profile patches (including S1/S2) match
31ab08d5; main's 11 disjoint native patches are preserved, the eight diagnostics stay absent, and protocol SHA-256 remainsa35addbd…606710. Fresh Tests (19 jobs), Code Quality (5 jobs), CLA, title validation and DeepScan all passed at this exact head. The three owner-deferred conversations are resolved, with their unvetted findings retained below.Profile-loader simplification (S1 + S2)
The existing-only loader no longer changes Chromium's public
ProfileManager::CreateProfileAsync.LoadExistingProfileByPathhandles the startup and unloading deferrals, checksCanCreateProfileAtPathand the catalog entry, then creates and registers the existing-only Profile itself when it owns a new load. It then joins the stockCreateProfileAsync, which finds the registered entry and runs or queues the callback. Only the call that registered reportsloaded:true; joining an in-flight or loaded profile reportsfalse.Profile::CreateProfilekeeps upstream's switch. An existing-only preflight precedes it, the asynchronous case skips directory creation, and the synchronous case refuses to create a directory that vanished after the preflight. Upstream'sprofile.hcomment andOnPrefsLoadedformatting are restored. The prefs-status check and the Windows cache guard are unchanged.Rebase surface in the profile family drops from 35 rewritten upstream lines and 23 zero-context hunks to 7 and 15.
profile_manager.{cc,h}are now pure insertions. The whole feature goes from +836/−71 to +817/−43. Native commit70a7f70a01c950b8300979aa497bd85974c13bbc(parent: reviewed profile tip5d203e25) is extracted here as31ab08d5. Four patch files changed; the other 13 profile patches and the remaining 390 store files are byte-identical. In that patch-only S1/S2 commit, the protocol (a35addbd…) and agent tree (2e4b96fa) were unchanged. The eight diagnostic paths remain absent.Verification
autoninja -C out/Default_browseros_arm64 chromepassed at exact70a7f70a(exit 0). GN/Ninja hashes and mtimes are unchanged, and a no-op re-run confirmed the target was current.CreateProfileAsync.31ab08d5(manually dispatched because the patch-only push is path-filtered): 18 jobs succeeded, including Claw server, Claw MCP, Claw server quality and the aggregate gate; only the dispatch-inapplicable summary was skipped.New targeted runtime on this macOS build (one healthy launch). The browser was launched directly from the reviewed output against a private fixture. A 1,054-file runtime closure was hashed identically before and after. There were no fatal or spawn lines, Crashpad helpers exited on their own, the leader exited 0, and nothing was left running.
true, repeat and already-loadedfalse.true.false. The load was started by the profile picker's statistics loader, and an ordering fence proved ours was pending.Preferences.49576d57standalone MCP host (same agent tree) bound eng, ran browser work in eng's window, then bound nik; laterrun/tabscalls used nik only.Async removal race: partial. The race was staged for real: an ordering fence proved the load pending past the native preflight, and the fixture directory was removed before any reply. It was not recreated after the reply or after shutdown. The underlying profile load does not complete. Upstream
JsonPrefStoremarks the readno_dirand never completes, and the Preferences/Secure PreferencesSegregatedPrefStorewaits for both stores, soOnPrefsLoadednever runs. Native replies "Profile load timed out" at 30 s, and that saved handle stays "still pending" until restart.The hang was observed on
70a7: after the 30 s native timeout, 180 s of subsequent observations still found the load pending, blocking that handle until browser restart. That it predates S1/S2 is a source-tracing inference, supported by the unchanged upstream prefs path and the older8e837timeout receipt; the previous candidate was not re-run for an experimental comparison. The owner accepts this documented limitation for this merge. It is reported, not fixed here. Also observed: failed loads of a profile with missing or corruptPreferencesleave stock tracked-prefs writingSecure Preferencesinto that existing directory.Not staged at runtime: a stock caller joining our in-flight load, the startup and unloading deferral paths, and synchronous existing-only mode (no caller). CI's Linux browser is not acceptance of the macOS build.
Earlier follow-up: diagnostic removal
The renderer-termination diagnostics were removed in
d3a8342e(eightcontent/browserpatches plus the feature entry). That native removal289b233ehad a tree identical to5d203e25. Its Tests run passed at that commit. At the diagnostic-removal and S1/S2 heads, the agent/Rust tree was identical to49576d57, which passed 984 executable tests, Rustdoc, formatting and strict Clippy; those patch-only updates added no Rust changes. The path-filtered Code Quality workflow did not run for these Chromium-only deltas; its prior run covered that unchanged agent tree. Current-main integration is verified separately. Historical 8e837 receipts stay historical and are not runtime proof for this candidate.Deferred external review
The owner explicitly deferred these three findings to TKT-1025, assigned to Nikhil Sonti (Todo, priority 1). They remain unvetted and unfixed. With explicit owner authorization, only their three blocking review conversations were resolved as accepted deferred follow-ups, preserving the original comments. This is not a fix, dismissal or vetting claim; no admin bypass was used.
Merge Danger
Door: two-way; no profile migration or new persisted profile database. Ship matching native and Rust components together.
Blast radius: native catalog/context routing, Rust admission and Claw task/group persistence. No owner live profile or installed application is used or replaced by these follow-ups. An existing-only load whose directory disappears mid-load stays pending until the native 30 s timeout and blocks that handle until restart (observed on
70a7; pre-existing status is source-tracing inference, not a previous-candidate rerun). A renderer destroyed while evaluation awaits a page promise can still leave that native command pending until the existing timeout. Commands without native expected-window/member preconditions retain a narrow physical-drag interval after the final observation.The owner now authorizes merging after current-main conflict resolution and exact-head CI, then a scoped patch-version+1 and macOS arm64-only Neo test draft. No live browser/component feed promotion, stable aliases or announcements are selected. Canonical native refresh will follow the actual merge under a new exclusive refresh lease. All task branches, worktrees, panes and historical evidence remain retained; no force push or installed-app change.
🤖 Generated with Claude Code