Commit Graph

1617 Commits

Author SHA1 Message Date
Magnus Müller 780274dc69 Merge branch 'main' into fix/session-handler-registration 2026-09-03 11:08:54 -07:00
Magnus Müller 57f60e4cf6 Merge branch 'main' into fix/issue-4471-fail-fast-browser-startup 2026-09-03 11:03:22 -07:00
Magnus Müller 3042d8c1df Merge branch 'main' into fix/session-handler-registration 2026-09-03 11:03:22 -07:00
Magnus Müller b78b3fcebd Merge branch 'main' into fix/session-handler-registration 2026-09-03 09:00:42 -07:00
Magnus Müller 8043fec5e6 Merge branch 'main' into fix/5569-send-keys-plus 2026-09-02 22:44:36 -07:00
Growth Radar QA df2701e524 fix(browser): preserve default Chrome arg order 2026-08-31 13:15:27 -07:00
Magnus Müller fa780c8e50 Merge branch 'main' into r266/storage-state-utf8 2026-08-30 23:04:21 -07:00
Magnus Müller 34d7978da9 Merge branch 'main' into fix/issue-5420-honor-browser-use-headless 2026-08-30 02:26:44 -07:00
Ronit Sawaiyan 230881a49b Merge branch 'main' into fix/5569-send-keys-plus 2026-08-29 02:07:43 +05:30
IENVYshanks 2b56dc8f59 test(browser): validate literal plus CDP key events 2026-08-28 23:08:25 +05:30
Magnus Müller 30b5aca5b0 Merge branch 'main' into fix/issue-5366 2026-08-28 02:25:57 -07:00
IENVYshanks 0a6e427c6f fix(browser): support literal plus in send_keys 2026-08-28 11:25:30 +05:30
Matthew Elliot 2f573908ca fix(browser): clear cookies via Storage domain, not Network
BrowserSession.clear_cookies() sends Network.clearBrowserCookies on the
root CDP client, which always fails:

  RuntimeError: {'code': -32601,
                 'message': "'Network.clearBrowserCookies' wasn't found"}

Network is a per-target domain and is not dispatchable without a session
attachment; the root client has none. Storage is browser-level, and the
cookies() getter two lines above already uses Storage.getCookies() there.

Measured against a live CDP endpoint:

  Network.clearBrowserCookies()                  REJECTED -32601
  Storage.clearCookies()                         OK
  Storage.clearCookies(session_id=...)           OK
  Network.clearBrowserCookies(session_id=...)    OK

The private _cdp_clear_cookies() already uses Storage.clearCookies with a
session_id, though its docstring still refers to Network.clearBrowserCookies
- this looks like the public method was missed when that one was fixed.
2026-08-27 13:06:53 +02:00
Aneesh Sharma 610c9614a9 fix(browser): honor BROWSER_USE_HEADLESS in BrowserProfile (#5420)
- Read BROWSER_USE_HEADLESS env var via default_factory in BrowserProfile

- Preserve fallback to display detection when env var is unset

- Add unit tests covering env var parsing and overrides

Fixes #5420
2026-08-15 23:41:56 +05:30
Saurav Panda 40010b3680 Merge branch 'main' into fix/issue-5365-coordinate-click-exception 2026-08-03 15:38:26 -07:00
santosh-agebold c9dae1b6bf fix: include exception details in coordinate click and add missing error logs 2026-08-03 13:13:40 -07:00
Shantanav 2c3162069e Fix reconnect drop handling during reconnect
Record WebSocket drops that occur during an in-flight reconnect and schedule a retry after the reconnect finishes.\n\nFixes #5366
2026-08-03 23:20:34 +05:30
r266-tech 33b4c2c44d fix(browser): read persisted storage state as UTF-8 2026-08-03 18:28:22 +08:00
Magnus Müller 8d29317136 Merge branch 'main' into fix/4257-storage-state-dict 2026-08-02 15:27:49 -07:00
Magnus Müller 81684831c1 Merge branch 'main' into fix/remote-download-complete-callback 2026-08-02 15:17:21 -07:00
Magnus Müller a5913e946e Merge branch 'main' into fix/profile-user-data-dir-return-type 2026-08-02 13:31:00 -07:00
sergioperezcheco 340851b09d fix(downloads): fire complete callbacks for remote-browser downloads
On a remote browser, the downloadProgress(completed) handler only dispatched FileDownloadedEvent on the event bus and never invoked the registered _download_complete_callbacks. The local branch does this inside _track_download(), so DefaultActionWatchdog._execute_click_with_download_detection waited on its on_download_complete asyncio.Event until the 30s timeout even though the download had finished.

Call the complete callbacks (with the same complete_info shape _track_download uses) right before dispatching the event in the remote branch. Adds a regression test that drives the registered downloadProgress handler and asserts the callback fires; the test fails on the unpatched code.
2026-07-28 09:12:29 +08:00
MagMueller 05b68eb567 test(browser): verify state recovery after timeout 2026-07-24 12:30:06 -07:00
MagMueller e7cc40f5ad fix(browser): expose minimal state after capture timeout 2026-07-24 11:51:16 -07:00
MagMueller 245cdd8dfc Revert "fix(browser): recover with cached state after timeout"
This reverts commit bd45e4c22a.
2026-07-24 10:38:26 -07:00
MagMueller b7ac967ea5 Revert "fix(browser): bound cached state recovery attempts"
This reverts commit 394ccc157e.
2026-07-24 10:38:26 -07:00
MagMueller 394ccc157e fix(browser): bound cached state recovery attempts 2026-07-23 21:59:58 -07:00
MagMueller bd45e4c22a fix(browser): recover with cached state after timeout 2026-07-23 21:59:58 -07:00
MagMueller 7f22c5a7b4 fix(browser): preserve DOM when state screenshots stall 2026-07-23 21:59:58 -07:00
MagMueller 5a4b02c4bd Keep selector indices unique across CDP sessions 2026-07-23 15:44:03 -07:00
MagMueller d4abb27612 review fixes: instanceof-guarded native setter (web components keep their own setter), drop dead honest-failure hunk, fix same descriptor bug in the concat-retry path
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:22:03 -07:00
MagMueller 369678054c input clear: fail honestly when a pure clear leaves text behind
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:22:03 -07:00
MagMueller 4ebc0f5d0d input clear: use native prototype value setter so React controlled inputs actually clear 2026-07-22 20:22:03 -07:00
ayaangazali b3b7e12fa3 fix(browser): apply storage_state cookies when passed as an in-memory dict
BrowserProfile.storage_state accepts str | Path | dict, but the
StorageStateWatchdog event handlers stringified the profile value
unconditionally. A dict became "{'cookies': [...]}", failed the
os.path.exists() check in _load_storage_state, and was silently
dropped, so cookies never reached the browser. The save path had the
same bug: the stringified dict was used as a file path, creating
junk directories named after the dict repr.

Preserve dicts through the event handlers, apply them directly in
_load_storage_state, and report a sentinel path in
StorageStateLoadedEvent instead of the repr (which would leak cookie
values). The existing dict guard in _save_storage_state is now
reachable via the event path.

Closes #4257
2026-07-20 11:21:55 -07:00
lisa0314 554ce8f99e Restore session handlers after event bus reset 2026-07-15 10:07:05 +08:00
Saurav Panda b4b6868232 Handle same-document navigations without burning the readiness timeout
Page.navigate omits loaderId for same-document navigations (#fragment,
History API), and Chrome emits no new load/DOMContentLoaded lifecycle events
for them — the navigation is already committed when Page.navigate returns.
The stale-event timestamp guard would otherwise reject all buffered events
and burn the full readiness timeout.

Short-circuit when loaderId is absent, and simplify the stale-event guard
(the no-navigation-id case can no longer reach it). Regression test drains
the previous load's trailing networkIdle first so a stale event can't
accidentally satisfy the wait.
2026-07-04 04:27:18 +08:00
Saurav Panda c5f0fa767c Fix navigation readiness detection: per-target lifecycle event storage
Navigation waits polled a per-session event deque whose feeding handler was
registered per-session on cdp-use's single-slot event registry. Any later
target attach replaced the handler, freezing existing tabs' deques with only
pre-navigation events, so every navigation on those tabs burned the full
readiness timeout (3s same-domain / 8s cross-domain) and then proceeded on a
page in unknown load state.

- Store lifecycle events per target_id in SessionManager, fed by ONE global
  Page.lifecycleEvent handler registered in start_monitoring() and routed by
  session_id; buffers are freed on target removal
- _navigate_and_wait reads the per-target buffer and now returns a timeout
  status string instead of swallowing readiness timeouts;
  on_NavigateToUrlEvent surfaces it via NavigationCompleteEvent.loading_status
- Skip loaderId-less lifecycle events that predate the current navigation
- Drop unused CDPSession._lifecycle_lock

Deterministic regression test: navigating tab A after opening tab B took
exactly the 3s fallback timeout before this fix, <0.5s after.
2026-07-03 22:48:20 +08:00
itxaiohanglover f2c871effb fix(browser): return Path from validate_user_data_dir when creating temp dir
tempfile.mkdtemp returns a str, but the other branch returns a Path.
Wrap in Path() for consistent return type.
2026-07-01 22:51:18 +08:00
Laith Weinberger 53c3ba2e72 Fix browser use CLI review issues 2026-06-29 14:00:13 +08:00
Laith Weinberger f768a06cfe new browser use CLI; new functions for deleted CLI methods 2026-06-29 13:10:55 +08:00
Saurav Panda 5123e4fc08 style: tighten ResilientEventBus docstring and comments 2026-06-26 15:56:17 +08:00
Saurav Panda 9c1db02dd3 fix(browser): preserve EventBus_ name prefix on ResilientEventBus
bubus derives the default bus name from the class name, so the
ResilientEventBus default factory changed session bus names from
EventBus_* to ResilientEventBus_*, breaking the EventBus_ prefix contract
asserted in tests/ci/browser/test_session_start.py. Default the subclass
name back to EventBus_<id> when none is given (explicit names still honored).
2026-06-26 15:48:59 +08:00
Saurav Panda 16c2745a37 fix(browser): tolerate stepping a torn-down event bus on warm-Lambda resume
The V2 worker reuses a keep_alive BrowserSession across warm Lambda
invocations. At the end of a run Agent.close() stops the session's event
bus and nulls out its async primitives (event_queue / _on_idle) to release
the event loop. On resume the worker can step() the bus before any
dispatch() restarts it, and stock bubus EventBus.step() asserts
"EventBus._start() must be called before step()" in that state — crashing
the run deterministically so the task dead-letters after max receives
(~1,600+ occurrences over 2 days).

Wrap the session's bus in a ResilientEventBus subclass whose step() and
wait_until_idle() are safe no-ops when the bus has not been started,
instead of asserting. The nulling stays (it's what lets the next dispatch()
recreate a fresh queue and _start() the bus), so a later dispatch() still
restarts the bus and processes events normally.

Fixes ENG-5280.
2026-06-26 13:28:53 +08:00
Magnus Müller c7da2c0e10 Fix Rust PR review feedback 2026-06-06 04:59:30 +00:00
Magnus Müller 1474c60da1 Merge remote-tracking branch 'upstream/main' into magnus/browser-use-rust-core-integration
# Conflicts:
#	browser_use/__init__.py
#	browser_use/agent/service.py
#	browser_use/browser/watchdogs/downloads_watchdog.py
#	browser_use/code_use/utils.py
#	browser_use/llm/models.py
#	browser_use/tokens/service.py
#	browser_use/utils.py
2026-06-04 16:14:57 +00:00
Magnus Müller 20e70519cf Filter generic network auto-downloads 2026-06-04 09:10:02 +00:00
Saurav Panda f0413fbd8c refactor(downloads): tighten download-sanitization comments
Drop the per-call-site rationale text; the helper names already convey
what's happening, and the WHY lives in the commit history. Shrink both
helper docstrings to one line.

No behavior change; 16/16 tests still pass.
2026-05-18 17:31:09 -07:00
Saurav Panda 29b03e43b4 Merge branch 'main' into fix/sec-download-path-traversal 2026-05-18 17:28:52 -07:00
Saurav Panda 4866656bba refactor(security): tighten _is_ip_address comments
Condense the running narrative across four prior fix commits into a single
docstring summarizing what canonicalization the function mirrors and the
never-throw invariant. Drop the per-step justifications — those live in
the commit messages where they belong.

No behavior change; 40/40 tests still pass.
2026-05-18 16:46:55 -07:00
Saurav Panda 7d061a0327 fix(security): fold IDNA label separators before IPv4 classification
Addresses third P1 codex review on #4866.

Per RFC 3490 / UTS46, four code points act as label separators in IDNA
processing — `.` (U+002E), `。` (U+3002 IDEOGRAPHIC FULL STOP),
`.` (U+FF0E FULLWIDTH FULL STOP), and `。` (U+FF61 HALFWIDTH IDEOGRAPHIC
FULL STOP). WHATWG URL parsing folds all four to `.` before resolution,
so `http://127。0。0。1/` and `http://127。0。0。1/` reach 127.0.0.1.

NFKC handles only U+FF0E and partially maps U+FF61 → U+3002, leaving the
IPv4 parser unable to match the dominant ideographic-dot form. Explicitly
replace U+3002 and U+FF61 with `.` after NFKC.

Test `test_idna_dot_separators_blocked` covers all four dot variants
both at `_is_url_allowed` and `_is_ip_address` levels, plus a combined
case with circled digits (`①②⑦。⓪。⓪。①`).
2026-05-18 16:40:24 -07:00