chromiumoxide/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::fmt;
use std::io;
use std::process::ExitStatus;
use std::time::Instant;

use base64::DecodeError;
use futures::channel::mpsc::SendError;
use futures::channel::oneshot::Canceled;
use thiserror::Error;
use tokio_tungstenite::tungstenite;
use tokio_tungstenite::tungstenite::Message;

use chromiumoxide_cdp::cdp::browser_protocol::page::FrameId;

use crate::handler::frame::NavigationError;
use chromiumoxide_cdp::cdp::js_protocol::runtime::ExceptionDetails;

pub type Result<T, E = CdpError> = std::result::Result<T, E>;

#[derive(Debug, Error)]
pub enum CdpError {
    #[error("{0}")]
    Ws(#[from] tungstenite::Error),
    #[error("{0}")]
    Io(#[from] io::Error),
    #[error("{0}")]
    Serde(#[from] serde_json::Error),
    #[error("{0}")]
    Chrome(#[from] chromiumoxide_types::Error),
    #[error("Received no response from the chromium instance.")]
    NoResponse,
    #[error("Received unexpected ws message: {0:?}")]
    UnexpectedWsMessage(Message),
    #[error("{0}")]
    ChannelSendError(#[from] ChannelError),
    #[error("Browser process exited with status {0:?} before websocket URL could be resolved, stderr: {1:?}")]
    LaunchExit(ExitStatus, BrowserStderr),
    #[error("Timeout while resolving websocket URL from browser process, stderr: {0:?}")]
    LaunchTimeout(BrowserStderr),
    #[error(
        "Input/Output error while resolving websocket URL from browser process, stderr: {1:?}: {0}"
    )]
    LaunchIo(#[source] io::Error, BrowserStderr),
    #[error("Request timed out.")]
    Timeout,
    #[error("FrameId {0:?} not found.")]
    FrameNotFound(FrameId),
    /// Error message related to a cdp response that is not a
    /// `chromiumoxide_types::Error`
    #[error("{0}")]
    ChromeMessage(String),
    #[error("{0}")]
    DecodeError(#[from] DecodeError),
    #[error("{0}")]
    ScrollingFailed(String),
    #[error("Requested value not found.")]
    NotFound,
    /// Detailed information about exception (or error) that was thrown during
    /// script compilation or execution
    #[error("{0:?}")]
    JavascriptException(Box<ExceptionDetails>),
    #[error("{0}")]
    Url(#[from] url::ParseError),
}
impl CdpError {
    pub fn msg(msg: impl Into<String>) -> Self {
        CdpError::ChromeMessage(msg.into())
    }
}

#[derive(Debug, Error)]
pub enum ChannelError {
    #[error("{0}")]
    Send(#[from] SendError),
    #[error("{0}")]
    Canceled(#[from] Canceled),
}

impl From<Canceled> for CdpError {
    fn from(err: Canceled) -> Self {
        ChannelError::from(err).into()
    }
}

impl From<SendError> for CdpError {
    fn from(err: SendError) -> Self {
        ChannelError::from(err).into()
    }
}

impl From<NavigationError> for CdpError {
    fn from(err: NavigationError) -> Self {
        match err {
            NavigationError::Timeout { .. } => CdpError::Timeout,
            NavigationError::FrameNotFound { frame, .. } => CdpError::FrameNotFound(frame),
        }
    }
}

/// An Error where `now > deadline`
#[derive(Debug, Clone)]
pub struct DeadlineExceeded {
    /// The deadline that was set.
    pub deadline: Instant,
    /// The current time
    pub now: Instant,
}

impl DeadlineExceeded {
    /// Creates a new instance
    ///
    /// panics if `now > deadline`
    pub fn new(now: Instant, deadline: Instant) -> Self {
        // assert!(now > deadline);
        Self { deadline, now }
    }
}

/// `stderr` output of the browser child process
///
/// This implements a custom `Debug` formatter similar to [`std::process::Output`]. If the output
/// is valid UTF-8, format as a string; otherwise format the byte sequence.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BrowserStderr(Vec<u8>);

impl BrowserStderr {
    pub fn new(stderr: Vec<u8>) -> Self {
        Self(stderr)
    }

    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.0
    }
}

impl fmt::Debug for BrowserStderr {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let stderr_utf8 = std::str::from_utf8(&self.0);
        let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
            Ok(ref str) => str,
            Err(_) => &self.0,
        };

        fmt.debug_tuple("BrowserStderr")
            .field(stderr_debug)
            .finish()
    }
}