Skip to main content

browser_control/session/
cdp_session.rs

1//! Transient flat-session helper for CDP page operations.
2//!
3//! Every CDP page op in `browser-control` follows the same shape: attach a
4//! flat session to the target, enable `Inspector` so renderer crashes are
5//! observable, run the op under the crash-detecting timeout, and detach
6//! regardless of outcome. This helper factors that shape so new native
7//! operations (accessibility tree, input dispatch) do not copy the block
8//! from `TabBackend::evaluate` a fourth time.
9
10use std::future::Future;
11use std::time::Duration;
12
13use anyhow::Result;
14use serde_json::json;
15
16use crate::cdp::CdpClient;
17use crate::session::crash::evaluate_with_crash_detection;
18
19/// Attach to `target_id`, run `f(session_id)` bounded by `timeout` with
20/// crash detection, then detach. Detach is best-effort: the target may
21/// already be gone, and the caller's result is what matters.
22pub async fn with_page_session<T, F, Fut>(
23    client: &CdpClient,
24    target_id: &str,
25    timeout: Duration,
26    f: F,
27) -> Result<T>
28where
29    F: FnOnce(String) -> Fut,
30    Fut: Future<Output = Result<T>>,
31{
32    let session_id = client.attach_to_target(target_id).await?;
33    // Best-effort, same rationale as `TabBackend::evaluate`: a failed
34    // enable would only mute crash detection.
35    let _ = client
36        .send_with_session("Inspector.enable", json!({}), Some(&session_id))
37        .await;
38    let fut = f(session_id.clone());
39    let result =
40        evaluate_with_crash_detection(client, target_id, Some(&session_id), fut, Some(timeout))
41            .await;
42    let _ = client
43        .send(
44            "Target.detachFromTarget",
45            json!({ "sessionId": session_id }),
46        )
47        .await;
48    result
49}