cdp: Input.dispatch* commands are not read while a page-triggered navigation (Enter submit, link click) loads; the next command times out
Before you start
- I searched existing issues and this is not a duplicate (#890 is about layout opening its own HTTP requests; this is about the connection processor not reading commands while a JS/form-triggered navigation loads).
- I tested against the latest release or
main(reproduced with the v0.2.2 stealth release binary and withmainat 727cc46). - This is not a security vulnerability.
obscura version or commit
v0.2.2 (a1e09de6) and main 727cc46
OS and architecture
Debian 13 x86_64
How are you using obscura?
CDP server with an own CDP client (Puppeteer/Playwright-style command sequences)
Affected area
CDP server / input handling / navigation
Build variant
Render-enabled with stealth (--features render,stealth); the code path is feature-independent
Stealth mode
On (--stealth), not relevant to the behaviour
Reproduction
When a CDP command makes the page schedule a document navigation, the navigation runs inline on the connection processor and nothing is read from the connection until the new document has loaded:
Input.dispatchKeyEventkeyDownEnter in a<form method=get>field: the command is answered, thenprocess_cdp_messagerunscheck_pending_navigationand dispatches the syntheticPage.navigateinline (crates/obscura-cdp/src/server.rs,process_cdp_message). The client's next command (the matchingkeyUp) is not read until the result page is fetched and loaded.Input.dispatchMouseEventmouseReleasedon a link or submit button: the handler itself awaitspage.process_pending_navigation()(crates/obscura-cdp/src/domains/input.rs), so themouseReleasedresponse is delayed by the whole navigation.
Chromium answers both input commands in milliseconds and dispatches the input to the outgoing document; the navigation loads while the client keeps sending commands. With Obscura a client that uses a per-command timeout (Puppeteer's default protocol timeout, or a scraper's per-action budget) times out whenever the target page needs longer than that timeout, although nothing is wrong with the page.
Minimal reproduction (offline, one local HTTP server that answers /slow after 1.5 s):
Page.navigateto<form method=get action=/slow><input id=q name=q></form>, wait for load.Runtime.evaluatedocument.getElementById('q').focus().Input.dispatchKeyEvent{type: keyDown, key: Enter, code: Enter, windowsVirtualKeyCode: 13}— answered immediately.Input.dispatchKeyEvent{type: keyUp, ...}— answered only after ~1.5 s (after the/slowdocument loaded). With a 10 s server delay and an 8 s client timeout thekeyUptimes out.
Same with <a href=/slow>: mousePressed is immediate, mouseReleased returns after the navigation.
Expected behavior
Input commands sent while a page-scheduled navigation is in flight are answered at once (Chromium timing), the navigation loads in the background through the same deferral loop that Page.navigate already uses, and the frame events (Page.frameStartedNavigating, Page.frameNavigated, ...) are emitted from there.
Actual behavior
The connection is not read until the navigation finished; the next command waits for the full document fetch.
Logs / additional context
Runtime.evaluate / Runtime.callFunctionOn have the same inline process_pending_navigation in crates/obscura-cdp/src/domains/runtime.rs; a navigation started from an evaluated expression still blocks that command (out of scope for the first fix, mentioned for completeness).
I have a fix ready and will open a PR referencing this issue.
Source: h4ckf0r0day/obscura