use serde_json::{Value, json};
use windows::core::{HRESULT, PCWSTR};
#[derive(Clone, Copy, Debug)]
pub(super) enum Stage {
Document,
Query { index: usize, root: i64 },
Html { index: usize, root: i64 },
}
#[derive(Debug)]
pub(super) struct Failure {
pub(super) error: windows::core::Error,
response: Option<String>,
decoding_error: Option<windows::core::Error>,
}
pub(super) type Reply = Result<Value, Failure>;
impl Failure {
pub(super) fn protocol(error: windows::core::Error, value: &Value) -> Self {
Self {
error,
response: Some(value.to_string()),
decoding_error: None,
}
}
pub(super) fn value(&self, operation: &str) -> Value {
json!({"kind":"native_error","operation":operation,"hresult":self.error.code().0,
"message":self.error.to_string(),"response":self.response,
"decoding_error":self.decoding_error.as_ref().map(|error|
json!({"hresult":error.code().0,"message":error.to_string()}))})
}
}
pub(super) unsafe fn read(status: HRESULT, result: &PCWSTR) -> Reply {
if let Err(error) = status.ok() {
let (response, decoding_error) = if result.is_null() {
(None, None)
} else {
match unsafe { super::super::text::read_borrowed_message(result) } {
Ok(response) => (Some(response), None),
Err(error) => (None, Some(error)),
}
};
return Err(Failure {
error,
response,
decoding_error,
});
}
let encoded =
unsafe { super::super::text::read_borrowed_message(result) }.map_err(|error| Failure {
error,
response: None,
decoding_error: None,
})?;
let value: Value = serde_json::from_str(&encoded).map_err(|error| Failure {
error: invalid(format!("WebView2 CDP JSON: {error}")),
response: Some(encoded.clone()),
decoding_error: None,
})?;
let error = if !value.is_object() {
Some(invalid("WebView2 CDP response is not an object"))
} else if value.get("error").is_some() {
Some(invalid("WebView2 CDP error response"))
} else {
None
};
if let Some(error) = error {
return Err(Failure {
error,
response: Some(encoded),
decoding_error: None,
});
}
Ok(value)
}
fn invalid(message: impl AsRef<str>) -> windows::core::Error {
windows::core::Error::new(windows::Win32::Foundation::E_ABORT, message.as_ref())
}