use std::sync::Arc;
use bao_cdp::servo_bridge::{bridge_channel, BridgeSender};
use bao_cdp::{handle_command, CdpMessage};
use bao_cdp_client::bridge::{BridgeSenderBackend, CDPRdpBridge};
use bao_cdp_client::transport::in_memory::{InMemoryBridge, InMemoryBridgeResponse};
const UNDRAINED_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(2);
pub struct MemoryCdpBridge {
sender: BridgeSender,
default_target: std::sync::Mutex<String>,
rdp: CDPRdpBridge,
}
impl MemoryCdpBridge {
pub fn new(
default_target: impl Into<String>,
) -> (Arc<Self>, bao_cdp::servo_bridge::BridgeReceiver) {
let (sender, receiver) = bridge_channel(UNDRAINED_TIMEOUT);
(Self::new_with_sender(default_target, sender), receiver)
}
pub fn set_default_target(&self, target: impl Into<String>) {
*self.default_target.lock().unwrap() = target.into();
}
pub fn event_tap(&self) -> Option<std::sync::Arc<bao_cdp_client::bridge::CdpEventTap>> {
self.rdp.backend().event_tap().cloned()
}
pub fn new_with_sender(default_target: impl Into<String>, sender: BridgeSender) -> Arc<Self> {
Arc::new(Self {
rdp: CDPRdpBridge::new(Arc::new(BridgeSenderBackend::new(sender.clone()))),
sender,
default_target: std::sync::Mutex::new(default_target.into()),
})
}
}
impl InMemoryBridge for MemoryCdpBridge {
fn dispatch_command(
&self,
method: &str,
params: serde_json::Value,
session_id: Option<&str>,
) -> InMemoryBridgeResponse {
let owned_default = self.default_target.lock().unwrap().clone();
let target = session_id.unwrap_or(&owned_default);
if let Some(response) = crate::screencast::dispatch_memory_command(method, ¶ms, target)
{
return response;
}
let msg = CdpMessage {
id: Some(0),
method: method.to_string(),
params: Some(params),
session_id: None,
};
let params_ref = msg.params.clone();
let response = handle_command(msg, target, ¶ms_ref, Some(&self.sender));
match response.error {
Some(err) if err.code == -32601 => {
let fallback_params = params_ref.clone().unwrap_or(serde_json::Value::Null);
match self.rdp.dispatch(target, method, fallback_params) {
Ok(v) => InMemoryBridgeResponse::Ok(v),
Err(
bao_cdp_client::bridge::BridgeError::MethodNotFound(_)
| bao_cdp_client::bridge::BridgeError::InvalidMethod(_),
) => InMemoryBridgeResponse::Err(err.message),
Err(e) => InMemoryBridgeResponse::Err(e.message()),
}
}
Some(err) => InMemoryBridgeResponse::Err(err.message),
None => InMemoryBridgeResponse::Ok(response.result.unwrap_or(serde_json::Value::Null)),
}
}
}