viewpoint_core/context/weberror/
mod.rs1use std::future::Future;
6use std::pin::Pin;
7
8use tracing::debug;
9use viewpoint_cdp::protocol::runtime::ExceptionThrownEvent;
10
11use super::BrowserContext;
12use crate::page::page_error::{PageError as PageErrorInfo, WebError};
13
14pub type WebErrorHandler = Box<
16 dyn Fn(WebError) -> Pin<Box<dyn Future<Output = ()> + Send>>
17 + Send
18 + Sync,
19>;
20
21impl BrowserContext {
22 pub(crate) fn start_weberror_listener(&self) {
24 let mut events = self.connection().subscribe_events();
25 let pages = self.pages.clone();
26 let weberror_handler = self.weberror_handler.clone();
27 let context_id = self.context_id().to_string();
28
29 tokio::spawn(async move {
30 while let Ok(event) = events.recv().await {
31 if event.method == "Runtime.exceptionThrown" {
32 if let Some(params) = &event.params {
33 if let Ok(exception_event) = serde_json::from_value::<ExceptionThrownEvent>(params.clone()) {
34 let session_id = event.session_id.clone().unwrap_or_default();
36
37 let target_id = {
39 let pages_guard = pages.read().await;
40 pages_guard.iter()
41 .find(|p| p.session_id == session_id)
42 .map(|p| p.target_id.clone())
43 .unwrap_or_default()
44 };
45
46 if target_id.is_empty() && session_id.is_empty() {
48 continue;
49 }
50
51 let page_error = PageErrorInfo::from_event(exception_event);
52 let web_error = WebError::new(page_error, target_id, session_id);
53
54 let handler = weberror_handler.read().await;
56 if let Some(ref h) = *handler {
57 h(web_error).await;
58 } else {
59 debug!("Web error in context {} (no handler): {}", context_id, web_error.message());
60 }
61 }
62 }
63 }
64 }
65 });
66 }
67
68 pub async fn on_weberror<F, Fut>(&self, handler: F)
84 where
85 F: Fn(WebError) -> Fut + Send + Sync + 'static,
86 Fut: Future<Output = ()> + Send + 'static,
87 {
88 let mut weberror_handler = self.weberror_handler.write().await;
89 *weberror_handler = Some(Box::new(move |error| {
90 Box::pin(handler(error))
91 }));
92 }
93
94 pub async fn off_weberror(&self) {
96 let mut weberror_handler = self.weberror_handler.write().await;
97 *weberror_handler = None;
98 }
99}