use crate::error::Result;
use crate::protocol::browser_context::Viewport;
use crate::protocol::{Dialog, Download, Request, ResponseObject, Route, WebSocket, Worker};
use crate::server::channel_owner::{ChannelOwner, ChannelOwnerImpl};
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::{AtomicBool, AtomicU64};
use std::sync::{Arc, Mutex, RwLock};
use crate::protocol::event_registry::EventRegistry;
#[derive(Clone)]
pub struct Page {
base: ChannelOwnerImpl,
main_frame: crate::protocol::Frame,
route_handlers: Arc<Mutex<Vec<RouteHandlerEntry>>>,
download: Arc<EventRegistry<Download>>,
dialog: Arc<EventRegistry<Dialog>>,
dialog_closed: Arc<EventRegistry<Dialog>>,
request: Arc<EventRegistry<Request>>,
request_finished: Arc<EventRegistry<Request>>,
request_failed: Arc<EventRegistry<Request>>,
response: Arc<EventRegistry<ResponseObject>>,
websocket_handlers: Arc<Mutex<Vec<WebSocketHandler>>>,
ws_route_handlers: Arc<Mutex<Vec<WsRouteHandlerEntry>>>,
viewport: Arc<RwLock<Option<Viewport>>>,
is_closed: Arc<AtomicBool>,
default_timeout_ms: Arc<AtomicU64>,
default_navigation_timeout_ms: Arc<AtomicU64>,
binding_callbacks: Arc<Mutex<HashMap<String, PageBindingCallback>>>,
screencast_frame_handlers: Arc<Mutex<Vec<ScreencastFrameHandler>>>,
screencast_artifact_guid: Arc<Mutex<Option<String>>>,
screencast_save_path: Arc<Mutex<Option<std::path::PathBuf>>>,
filechooser: Arc<EventRegistry<crate::protocol::FileChooser>>,
console: Arc<EventRegistry<crate::protocol::ConsoleMessage>>,
close: Arc<EventRegistry<()>>,
load: Arc<EventRegistry<()>>,
crash: Arc<EventRegistry<()>>,
pageerror: Arc<EventRegistry<String>>,
popup: Arc<EventRegistry<Page>>,
frameattached: Arc<EventRegistry<crate::protocol::Frame>>,
framedetached: Arc<EventRegistry<crate::protocol::Frame>>,
framenavigated: Arc<EventRegistry<crate::protocol::Frame>>,
worker_handlers: Arc<Mutex<Vec<WorkerHandler>>>,
worker_waiters: Arc<Mutex<Vec<tokio::sync::oneshot::Sender<crate::protocol::Worker>>>>,
console_messages_log: Arc<Mutex<Vec<crate::protocol::ConsoleMessage>>>,
page_errors_log: Arc<Mutex<Vec<String>>>,
workers_list: Arc<Mutex<Vec<Worker>>>,
video: Option<crate::protocol::Video>,
locator_handlers: Arc<Mutex<Vec<LocatorHandlerEntry>>>,
}
type RouteHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type WebSocketHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type WebSocketRouteHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
#[derive(Clone)]
struct WsRouteHandlerEntry {
pattern: String,
handler:
Arc<dyn Fn(crate::protocol::WebSocketRoute) -> WebSocketRouteHandlerFuture + Send + Sync>,
}
#[derive(Clone)]
struct RouteHandlerEntry {
pattern: String,
handler: Arc<dyn Fn(Route) -> RouteHandlerFuture + Send + Sync>,
}
type WebSocketHandler = Arc<dyn Fn(WebSocket) -> WebSocketHandlerFuture + Send + Sync>;
type ScreencastFrameHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type ScreencastFrameHandler =
Arc<dyn Fn(crate::protocol::ScreencastFrame) -> ScreencastFrameHandlerFuture + Send + Sync>;
type WorkerHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type WorkerHandler = Arc<dyn Fn(crate::protocol::Worker) -> WorkerHandlerFuture + Send + Sync>;
type PageBindingCallbackFuture = Pin<Box<dyn Future<Output = serde_json::Value> + Send>>;
type PageBindingCallback =
Arc<dyn Fn(Vec<serde_json::Value>) -> PageBindingCallbackFuture + Send + Sync>;
type LocatorHandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type LocatorHandlerFn = Arc<dyn Fn(crate::protocol::Locator) -> LocatorHandlerFuture + Send + Sync>;
struct LocatorHandlerEntry {
uid: u32,
selector: String,
handler: LocatorHandlerFn,
times_remaining: Option<u32>,
}
mod lifecycle;
mod navigation;
mod evaluate;
mod input;
mod events;
mod network;
mod bindings;
mod capture;
mod emulation;
mod response;
mod dispatch;
pub use bindings::AddLocatorHandlerOptions;
pub use capture::{PdfMargin, PdfOptions, PdfOptionsBuilder};
pub use emulation::{
AddScriptTagOptions, AddScriptTagOptionsBuilder, AddStyleTagOptions, AddStyleTagOptionsBuilder,
ColorScheme, EmulateMediaOptions, EmulateMediaOptionsBuilder, ForcedColors, Media,
ReducedMotion,
};
pub use navigation::{GotoOptions, WaitUntil};
pub use network::RouteFromHarOptions;
pub use response::Response;
impl std::fmt::Debug for Page {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Page")
.field("guid", &self.guid())
.field("url", &self.url())
.finish()
}
}
pub(crate) async fn set_timeout_and_notify(
channel: &crate::server::channel::Channel,
method: &str,
timeout: f64,
) {
if let Err(e) = channel
.send_no_result(method, serde_json::json!({ "timeout": timeout }))
.await
{
tracing::warn!("{} send error: {}", method, e);
}
}