cdp_html_shot/browser/browser_utils.rs
1use regex::Regex;
2use anyhow::{Context, Result};
3use std::io::{BufRead, BufReader};
4use std::process::{ChildStderr, Command, Stdio};
5
6use crate::browser::browser_config::BrowserConfig;
7
8pub(crate) fn spawn_chrome_process(config: &BrowserConfig) -> Result<std::process::Child> {
9 let mut command = Command::new(&config.executable_path);
10
11 #[cfg(windows)]
12 configure_windows_process(&mut command);
13
14 command
15 .args(config.get_browser_args())
16 .stderr(Stdio::piped())
17 .spawn()
18 .context("Failed to spawn a Chrome process")
19}
20
21#[cfg(windows)]
22fn configure_windows_process(command: &mut Command) {
23 use std::os::windows::process::CommandExt;
24 const CREATE_NO_WINDOW: u32 = 0x08000000;
25 command.creation_flags(CREATE_NO_WINDOW);
26}
27
28pub(crate) async fn get_websocket_url(stderr: ChildStderr) -> Result<String> {
29 let reader = BufReader::new(stderr);
30 ws_url_from_reader(reader)
31 .await?
32 .context("Failed to get ws url")
33}
34
35async fn ws_url_from_reader(reader: BufReader<ChildStderr>) -> Result<Option<String>>
36{
37 let re = Regex::new(r"listening on (.*/devtools/browser/.*)$")?;
38
39 let extract = |text: &str| -> Option<String> {
40 let caps = re.captures(text);
41 let cap = &caps?[1];
42 Some(cap.into())
43 };
44
45 for line in reader.lines() {
46 if let Some(answer) = extract(&line?) {
47 return Ok(Some(answer));
48 }
49 }
50 Ok(None)
51}