use std::fmt::Debug;
use crate::{
cdp::{
self,
commands::{CDPCommand, RuntimeEvaluate, TargetAttachToTarget, TargetGetTargets},
Cdp,
},
error::CrowserError,
};
pub struct BrowserIpc {
cdp: Cdp,
session_id: String,
}
impl Debug for BrowserIpc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "BrowserIpc")
}
}
impl BrowserIpc {
pub fn new(port: u16) -> Result<Self, CrowserError> {
let cdp = cdp::launch(port)?;
let mut ipc = BrowserIpc {
cdp,
session_id: String::new(),
};
ipc.attach()?;
Ok(ipc)
}
pub fn attach(&mut self) -> Result<(), CrowserError> {
let t_params = TargetGetTargets {};
let t_cmd = CDPCommand::new("Target.getTargets", t_params, None);
let result = self.cdp.send(t_cmd, None)?;
let result = result.get("result");
let targets = match result {
Some(val) => val,
None => return Err(CrowserError::CDPError("No result found".to_string())),
};
let targets = match targets.get("targetInfos") {
Some(val) => val,
None => return Err(CrowserError::CDPError("No targets found".to_string())),
}
.as_array();
if let Some(targets) = targets {
for target in targets {
let t = target["type"].as_str().unwrap_or_default();
if t != "page" {
continue;
}
let t_params = TargetAttachToTarget {
target_id: target["targetId"].as_str().unwrap_or_default().to_string(),
flatten: true,
};
let t_cmd = CDPCommand::new("Target.attachToTarget", t_params, None);
self.cdp.send(t_cmd, None)?;
let evt_result = self.cdp.wait_for_event("Target.attachedToTarget", None)?;
let evt_result = evt_result.params.get("sessionId");
if let Some(session_id) = evt_result {
self.session_id = session_id.as_str().unwrap_or_default().to_string();
break;
}
}
}
let cmd = CDPCommand::new(
"Runtime.enable",
serde_json::Value::Null,
Some(self.session_id.clone()),
);
self.cdp.send(cmd, None)?;
Ok(())
}
pub fn eval(&mut self, script: &str) -> Result<String, CrowserError> {
let params = RuntimeEvaluate {
expression: script.to_string(),
};
let cmd = CDPCommand::new("Runtime.evaluate", params, Some(self.session_id.clone()));
let result = self.cdp.send(cmd, None)?;
let result = match result["result"]["result"].get("value") {
Some(val) => val,
None => return Err(CrowserError::CDPError("No result found".to_string())),
};
Ok(result.to_string())
}
}