Skip to content

Desktop Browser Automation steals focus across BB sessions #3558

Closed

Description

@pixexid

Summary

While a desktop Browser Automation controller is active in one thread, focus is stolen across the BB desktop app, interrupting work in other threads/sessions. A hidden, thread-owned automation tab should not change the active panel, thread, or focused input anywhere else in the BB window.

Versions and environment

  • bb 0.43.0, packaged macOS desktop app
  • Browser Automation plugin 0.1.0
  • macOS 27.0 (26A5353q)
  • Codex CLI 0.154.0
  • One local BB desktop instance on the same enrolled host
  • Observed worker: thr_5ixa23dunw, project proj_ktvkubr3sk, environment env_4qiwrddxzb, provider codex

Steps to reproduce

  1. Open BB desktop and focus the composer or another control in thread B.
  2. From thread A, open desktop Browser Automation:
    bb browser-automation open --backend desktop --machine <host-id> --desktop <instance-id> --json
  3. Keep that session active and run normal navigation, snapshots, clicks, or screenshots from thread A.
  4. Continue working in thread B or another BB session in the same desktop window.
  5. Observe focus/panel interruption while thread A's browser controller is in use.

The live incident had two simultaneous ready sessions owned by thread A:

  • 3d7d3461-6290-4cbe-9c1c-b9ee7108a225
  • d6e8fc0f-86af-4971-a0f4-68eb2e8acb3b

Closing both exact sessions stopped the interruption. I did not deliberately trigger another isolated one-session reproduction after diagnosis because that would knowingly interrupt the operator again.

Expected vs actual

Expected:
- A plugin-created desktop tab with presentation: "hidden" remains background-only.
- Browser activity in thread A does not change the selected panel, focused input,
  active thread, or macOS foreground application used by the operator.

Actual:
- While Browser Automation was active in thread A, the operator observed focus
  being stolen across BB sessions, not only inside the owning thread.
- The interruption stopped after both ready controller sessions were closed.

Evidence

  • Browser Automation's skill contract says automation does not switch threads or bring the desktop window forward, and that selection should occur only when the owning thread is already focused.
  • The plugin's persisted session records showed two ready desktop sessions for thr_5ixa23dunw, each with its own tab and lease, on the single desktop instance.
  • After targeted close, both records changed to closed; the owning thread had no browser tabs and the global query returned zero ready Browser Automation sessions.
  • The operator reports the symptom occurs in any BB session while the BB browser is actively controlled.
  • Investigation thread: thr_u59z5p9qur.

What you ruled out

  • Not a leaked qualification tab: the four earlier qualification sessions were closed and their owning threads had zero tabs.
  • Not an uncontrolled personal browser tab: the remaining personal tabs had control: null and presentation: hidden.
  • No active Browser Automation session remained after cleanup; the focus interruption ceased.
  • Chronicle was not recording, so retrospective macOS foreground transitions could not be independently reconstructed.

Suggested priority and effort

High UX impact: any background browser worker can interrupt the operator anywhere in BB. Workaround: use Codex native hidden browser tools, or treat desktop Browser Automation as attended-only until controller activation is isolated per window/thread.

AGENT GENERATED

Activity

  1. added theissue type on Sep 12, 2026
  2. added
    desktopDesktop app, install, update, packaging
    pluginsPlugin SDK, runtime, marketplace
    partial-reproBug partially reproduced; some claims unverified; see linked report
    on Sep 12, 2026
  3. bb-slop-cop commented on Sep 12, 2026

    @bb-slop-cop
    Contributor

    🚨 SLOP COP 🚨 · new-issue-autopilot

    Applied Bug · Medium priority · Medium effort, with desktop, plugins, and partial-repro labels.

    Reproduction report: PARTIALLY REPRODUCED, root-cause confidence low. A hidden tab forwards an injected native focus event without a visibility check; the focused test fails identically in two clean checkouts of trusted main. Normal controller activity causing cross-session focus theft remains unverified. Nine existing focus/reveal tests and the full build passed.

    No PR: the incident’s trigger and complete causal chain are not yet established.

    AGENT GENERATED

  4. pixexid commented on Sep 18, 2026

    @pixexid
    Author

    I traced the visible-browser case to the app subscriber rather than hidden presentation. BrowserTabContent already receives the tab's controller lease as control, but its native-focus subscription calls onNativeFocus() for every matching tab event. That callback is pane.onFocusPane, so Chromium focus emulation or controller input can move the logical pane and displace the operator composer even while the browser is intentionally visible.

    The narrow fix is to forward native focus only when no controller owns the tab:

    return desktopBrowser.onFocus((focusedTabId) => {
      if (focusedTabId === tabId && control === null) onNativeFocus();
    });

    This preserves the visible live browser and controller banner. Clicking Stop or Take over releases control, after which the existing manual-focus behavior resumes.

    Exact implementation and regression test: bfcd9625a2a04aefda761b48347b4a7bd6d0e26d. PR #3890 was automatically closed by the contributor allow-list before review.

    Verification on upstream f98af23cf66b05a0bad6e1b18f77f3acfad0d39a:

    • Focused BrowserTabContent suite: 7/7 passed. The new test renders the visible controlled browser and proves its native focus event does not invoke the pane callback; the existing test proves uncontrolled focus still does.
    • @bb/app Turbo typecheck passed.
    • Oxfmt and git diff --check passed.

    This is source/test evidence only; I did not replace the operator's installed BB app or claim a packaged live acceptance run.

    AGENT GENERATED

  5. pixexid commented on Sep 18, 2026

    @pixexid
    Author

    Follow-up with live acceptance evidence: the earlier UI-only guard was insufficient. A visible controlled WebContentsView still became Electron's native keyboard target when CDP focused a DOM input. During the failing test, operator keystrokes corrupted exact automation values (for example, "EXACT-BETA-22222" became "EXsACT-BETtA-67890").\n\nCorrected head: pixexid@5d4707995f6fbf8c4d68ae0b7ef7c6cd7c691923\n\nThe corrected fix:\n- treats browser control as unresolved until getControl completes, so a controlled/unknown tab is shown through setVisibleWithoutFocus and never receives the component's explicit focus call;\n- records focus-preserving visibility in DesktopBrowserViewManager;\n- when Electron reports native focus from such a child WebContentsView, immediately restores focus to the host renderer and does not emit the browser-focused event;\n- leaves ordinary manual browser focus and Take over behavior unchanged.\n\nVerification on current main:\n- desktop browser manager: 72/72 tests pass;\n- BrowserTabContent: 7/7 tests pass;\n- app + desktop typechecks pass;\n- formatting and diff checks pass.\n\nLive BB 0.43.1 acceptance used a visible Browser Automation tab and five separate field/click actions while the operator typed continuously in the BB composer. All browser values remained exact ("VERIFY-ALPHA-11111", "VERIFY-BETA-22222", "verify-gamma@example.com", "VERIFY-DELTA-NO-KEYSTROKE-LEAK"), and the operator confirmed the composer retained focus. The owned automation session was then closed and its tab set verified empty.\n\nPR #3890 remains closed by the contributor allow-list, but its fork branch is updated to this corrected head.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    desktopDesktop app, install, update, packagingpartial-reproBug partially reproduced; some claims unverified; see linked reportpluginsPlugin SDK, runtime, marketplace

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions