1use std::fmt;
2use std::io;
3use std::process::ExitStatus;
4use std::time::Instant;
5
6use base64::DecodeError;
7use thiserror::Error;
8use tokio_tungstenite::tungstenite;
9use tokio_tungstenite::tungstenite::Message;
10use chromiumoxide_cdp::cdp::browser_protocol::page::FrameId;
11
12use crate::handler::frame::NavigationError;
13use chromiumoxide_cdp::cdp::js_protocol::runtime::ExceptionDetails;
14
15pub type Result<T, E = CdpError> = std::result::Result<T, E>;
16
17#[derive(Debug, Error)]
18pub enum CdpError {
19 #[error("{0}")]
20 Ws(#[from] tungstenite::Error),
21 #[error("{0}")]
22 Io(#[from] io::Error),
23 #[error("{0}")]
24 Serde(#[from] serde_json::Error),
25 #[error("{0}")]
26 #[cfg(feature = "simd")]
27 SerdeSonic(#[from] sonic_rs::Error),
28 #[error("{0}")]
29 Chrome(#[from] chromiumoxide_types::Error),
30 #[error("Received no response from the chromium instance.")]
31 NoResponse,
32 #[error("Received unexpected ws message: {0:?}")]
33 UnexpectedWsMessage(Message),
34 #[error("{0}")]
35 ChannelSendError(#[from] ChannelError),
36 #[error("Browser process exited with status {0:?} before websocket URL could be resolved, stderr: {1:?}")]
37 LaunchExit(ExitStatus, BrowserStderr),
38 #[error("Timeout while resolving websocket URL from browser process, stderr: {0:?}")]
39 LaunchTimeout(BrowserStderr),
40 #[error(
41 "Input/Output error while resolving websocket URL from browser process, stderr: {1:?}: {0}"
42 )]
43 LaunchIo(#[source] io::Error, BrowserStderr),
44 #[error("Request timed out.")]
45 Timeout,
46 #[error("FrameId {0:?} not found.")]
47 FrameNotFound(FrameId),
48 #[error("{0}")]
51 ChromeMessage(String),
52 #[error("{0}")]
53 DecodeError(#[from] DecodeError),
54 #[error("{0}")]
55 ScrollingFailed(String),
56 #[error("Requested value not found.")]
57 NotFound,
58 #[error("{0:?}")]
61 JavascriptException(Box<ExceptionDetails>),
62 #[error("{0}")]
63 Url(#[from] url::ParseError),
64}
65
66impl CdpError {
67 pub fn msg(msg: impl Into<String>) -> Self {
68 CdpError::ChromeMessage(msg.into())
69 }
70}
71
72#[derive(Debug, Error)]
73pub enum ChannelError {
74 #[error("channel closed")]
75 Send,
76 #[error("{0}")]
77 Canceled(#[from] tokio::sync::oneshot::error::RecvError),
78}
79
80impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ChannelError {
81 fn from(_: tokio::sync::mpsc::error::SendError<T>) -> Self {
82 ChannelError::Send
83 }
84}
85
86impl<T> From<tokio::sync::mpsc::error::SendError<T>> for CdpError {
87 fn from(err: tokio::sync::mpsc::error::SendError<T>) -> Self {
88 ChannelError::from(err).into()
89 }
90}
91
92impl<T> From<tokio::sync::mpsc::error::TrySendError<T>> for CdpError {
93 fn from(_: tokio::sync::mpsc::error::TrySendError<T>) -> Self {
94 ChannelError::Send.into()
95 }
96}
97
98impl From<tokio::sync::oneshot::error::RecvError> for CdpError {
99 fn from(err: tokio::sync::oneshot::error::RecvError) -> Self {
100 ChannelError::from(err).into()
101 }
102}
103
104impl From<NavigationError> for CdpError {
105 fn from(err: NavigationError) -> Self {
106 match err {
107 NavigationError::Timeout { .. } => CdpError::Timeout,
108 NavigationError::FrameNotFound { frame, .. } => CdpError::FrameNotFound(frame),
109 }
110 }
111}
112
113#[derive(Debug, Clone)]
115pub struct DeadlineExceeded {
116 pub deadline: Instant,
118 pub now: Instant,
120}
121
122impl DeadlineExceeded {
123 pub fn new(now: Instant, deadline: Instant) -> Self {
127 Self { deadline, now }
129 }
130}
131
132#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
137pub struct BrowserStderr(Vec<u8>);
138
139impl BrowserStderr {
140 pub fn new(stderr: Vec<u8>) -> Self {
141 Self(stderr)
142 }
143
144 pub fn as_slice(&self) -> &[u8] {
145 &self.0
146 }
147
148 pub fn into_vec(self) -> Vec<u8> {
149 self.0
150 }
151}
152
153impl fmt::Debug for BrowserStderr {
154 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
155 let stderr_utf8 = std::str::from_utf8(&self.0);
156 let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
157 Ok(ref str) => str,
158 Err(_) => &self.0,
159 };
160
161 fmt.debug_tuple("BrowserStderr")
162 .field(stderr_debug)
163 .finish()
164 }
165}