1use anyhow::{anyhow, Result};
2use chromiumoxide::{
3 fetcher::BrowserFetcherRevisionInfo, Browser, BrowserConfig, BrowserFetcher,
4 BrowserFetcherOptions, Page,
5};
6use std::path::Path;
7use tokio::time::{sleep, Duration};
8use tokio_stream::StreamExt;
9use tracing::debug;
10
11pub async fn init(browser_path: &Path, user_data_dir: &Path, headless: bool) -> Result<Browser> {
26 let browser_info = ensure_browser(browser_path).await?;
27
28 let mut config = BrowserConfig::builder()
29 .user_data_dir(user_data_dir)
30 .chrome_executable(browser_info.executable_path);
31
32 if headless {
33 config = config.with_head();
34 }
35
36 let (browser, mut handler) = Browser::launch(config.build().map_err(|e| anyhow!(e))?).await?;
37
38 tokio::spawn(async move {
39 while let Some(h) = handler.next().await {
40 if h.is_err() {
41 debug!("Browser handler error: {:?}", h);
42 break;
43 }
44 }
45 });
46
47 Ok(browser)
48}
49
50async fn ensure_browser(path: &Path) -> Result<BrowserFetcherRevisionInfo> {
51 let fetcher = BrowserFetcher::new(BrowserFetcherOptions::builder().with_path(path).build()?);
52
53 Ok(fetcher.fetch().await?)
54}
55
56pub async fn wait_for_page(page: &Page) {
62 tokio::select! {
63 _ = page.wait_for_navigation() => {},
64 _ = sleep(Duration::from_secs(5)) => {},
65 }
66}