1use crate::imp::{
2 browser_context::BrowserContext,
3 console_message::ConsoleMessage,
4 core::*,
5 download::Download,
6 element_handle::may_save,
7 file_hooser::FileChooser,
8 frame::Frame,
9 prelude::*,
10 request::Request,
11 response::Response,
12 utils::{
13 ColorScheme, DocumentLoadState, FloatRect, Header, Length, MouseButton, PdfMargins,
14 ScreenshotType, Viewport
15 },
16 video::Video,
17 websocket::WebSocket,
18 worker::Worker
19};
20
21#[derive(Debug)]
22pub(crate) struct Page {
23 channel: ChannelOwner,
24 main_frame: Weak<Frame>,
25 browser_context: Weak<BrowserContext>,
26 var: Mutex<Variable>,
27 tx: Mutex<Option<broadcast::Sender<Evt>>>
28}
29
30#[derive(Debug, Default)]
31pub(crate) struct Variable {
32 viewport: Option<Viewport>,
33 frames: Vec<Weak<Frame>>,
34 timeout: Option<u32>,
35 navigation_timeout: Option<u32>,
36 workers: Vec<Weak<Worker>>,
37 video: Option<Video>
38}
39
40macro_rules! navigation {
41 ($f: ident, $m: literal) => {
42 pub(crate) async fn $f(
43 &self,
44 args: ReloadArgs
45 ) -> Result<Option<Weak<Response>>, Arc<Error>> {
46 let v = send_message!(self, $m, args);
47 let guid = match as_only_guid(&v) {
48 Some(g) => g,
49 None => return Ok(None)
50 };
51 let r = get_object!(self.context()?.lock().unwrap(), &guid, Response)?;
52 Ok(Some(r))
53 }
54 };
55}
56
57macro_rules! mouse_down {
58 ($f:ident, $m:literal) => {
59 pub(crate) async fn $f(
60 &self,
61 button: Option<MouseButton>,
62 click_count: Option<i32>
63 ) -> Result<(), Arc<Error>> {
64 #[skip_serializing_none]
65 #[derive(Serialize)]
66 #[serde(rename_all = "camelCase")]
67 struct Args {
68 button: Option<MouseButton>,
69 click_count: Option<i32>
70 }
71 let args = Args {
72 button,
73 click_count
74 };
75 let _ = send_message!(self, $m, args);
76 Ok(())
77 }
78 };
79}
80
81impl Page {
82 const DEFAULT_TIMEOUT: u32 = 30000;
83
84 pub(crate) fn try_new(ctx: &Context, channel: ChannelOwner) -> Result<Self, Error> {
85 let Initializer {
86 main_frame: OnlyGuid { guid },
87 viewport
88 } = serde_json::from_value(channel.initializer.clone())?;
89 let browser_context = match &channel.parent {
90 Some(RemoteWeak::BrowserContext(c)) => c.clone(),
91 _ => return Err(Error::InvalidParams)
92 };
93 let main_frame = get_object!(ctx, &guid, Frame)?;
94 let var = Mutex::new(Variable {
95 frames: vec![main_frame.clone()],
96 viewport,
97 ..Variable::default()
98 });
99 Ok(Self {
100 channel,
101 main_frame,
102 browser_context,
103 var,
104 tx: Mutex::default()
105 })
106 }
107
108 pub(crate) fn hook_created(&self, this: Weak<Page>) -> Result<(), Error> {
109 upgrade(&self.main_frame)?.set_page(this);
110 Ok(())
111 }
112
113 pub(crate) fn browser_context(&self) -> Weak<BrowserContext> { self.browser_context.clone() }
114
115 pub(crate) fn main_frame(&self) -> Weak<Frame> { self.main_frame.clone() }
116
117 navigation! {reload, "reload"}
118 navigation! {go_back, "goBack"}
119 navigation! {go_forward, "goForward"}
120
121 pub(crate) async fn key_down(&self, key: &str) -> Result<(), Arc<Error>> {
122 let mut args = HashMap::new();
123 args.insert("key", key);
124 let _ = send_message!(self, "keyboardDown", args);
125 Ok(())
126 }
127
128 pub(crate) async fn key_up(&self, key: &str) -> Result<(), Arc<Error>> {
129 let mut args = HashMap::new();
130 args.insert("key", key);
131 let _ = send_message!(self, "keyboardUp", args);
132 Ok(())
133 }
134
135 pub(crate) async fn key_input_text(&self, text: &str) -> Result<(), Arc<Error>> {
136 let mut args = HashMap::new();
137 args.insert("text", text);
138 let _ = send_message!(self, "keyboardInsertText", args);
139 Ok(())
140 }
141
142 pub(crate) async fn key_type(&self, text: &str, delay: Option<f64>) -> Result<(), Arc<Error>> {
143 #[skip_serializing_none]
144 #[derive(Serialize)]
145 #[serde(rename_all = "camelCase")]
146 struct Args<'b> {
147 text: &'b str,
148 delay: Option<f64>
149 }
150 let args = Args { text, delay };
151 let _ = send_message!(self, "keyboardInsertText", args);
152 Ok(())
153 }
154
155 pub(crate) async fn key_press(&self, text: &str, delay: Option<f64>) -> Result<(), Arc<Error>> {
156 #[skip_serializing_none]
157 #[derive(Serialize)]
158 #[serde(rename_all = "camelCase")]
159 struct Args<'b> {
160 text: &'b str,
161 delay: Option<f64>
162 }
163 let args = Args { text, delay };
164 let _ = send_message!(self, "keyboardPress", args);
165 Ok(())
166 }
167
168 pub(crate) async fn screen_tap(&self, x: f64, y: f64) -> Result<(), Arc<Error>> {
169 #[derive(Serialize)]
170 #[serde(rename_all = "camelCase")]
171 struct Args {
172 x: f64,
173 y: f64
174 }
175 let args = Args { x, y };
176 let _ = send_message!(self, "touchscreenTap", args);
177 Ok(())
178 }
179
180 pub(crate) async fn mouse_move(
181 &self,
182 x: f64,
183 y: f64,
184 steps: Option<i32>
185 ) -> Result<(), Arc<Error>> {
186 #[skip_serializing_none]
187 #[derive(Serialize)]
188 #[serde(rename_all = "camelCase")]
189 struct Args {
190 x: f64,
191 y: f64,
192 steps: Option<i32>
193 }
194 let args = Args { x, y, steps };
195 let _ = send_message!(self, "mouseMove", args);
196 Ok(())
197 }
198
199 mouse_down! {mouse_down, "mouseDown"}
200 mouse_down! {mouse_up, "mouseUp"}
201
202 pub(crate) async fn mouse_click(&self, args: MouseClickArgs) -> Result<(), Arc<Error>> {
203 let _ = send_message!(self, "mouseClick", args);
204 Ok(())
205 }
206
207 pub(crate) async fn mouse_dblclick(&self, args: MouseClickArgs) -> Result<(), Arc<Error>> {
208 let args = MouseClickArgs {
209 click_count: Some(2),
210 ..args
211 };
212 self.mouse_click(args).await
213 }
214
215 pub(crate) async fn accessibility_snapshot(
216 &self,
217 args: AccessibilitySnapshotArgs
218 ) -> ArcResult<Option<AccessibilitySnapshotResponse>> {
219 let v = send_message!(self, "accessibilitySnapshot", args);
220 let first = match first(&v) {
221 None => return Ok(None),
222 Some(x) => x
223 };
224 let res: AccessibilitySnapshotResponse =
225 serde_json::from_value((*first).clone()).map_err(Error::Serde)?;
226 Ok(Some(res))
227 }
228
229 pub(crate) async fn bring_to_front(&self) -> ArcResult<()> {
230 let _ = send_message!(self, "bringToFront", Map::new());
231 Ok(())
232 }
233
234 pub(crate) async fn add_init_script(&self, source: &str) -> ArcResult<()> {
235 let mut args = HashMap::new();
236 args.insert("source", source);
237 let _ = send_message!(self, "addInitScript", args);
238 Ok(())
239 }
240
241 pub(crate) async fn pdf(
242 &self,
243 args: PdfArgs<'_, '_, '_, '_, '_, '_, '_, '_, '_, '_>
244 ) -> ArcResult<Vec<u8>> {
245 let path = args.path.clone();
246 let v = send_message!(self, "pdf", args);
247 let b64 = only_str(&v)?;
248 let bytes = base64::decode(b64).map_err(Error::InvalidBase64)?;
249 may_save(path.as_deref(), &bytes)?;
250 Ok(bytes)
251 }
252
253 pub(crate) async fn close(&self, run_before_unload: Option<bool>) -> Result<(), Arc<Error>> {
254 #[skip_serializing_none]
255 #[derive(Serialize)]
256 #[serde(rename_all = "camelCase")]
257 struct Args {
258 run_before_unload: Option<bool>
259 }
260 let args = Args { run_before_unload };
261 let _ = send_message!(self, "close", args);
262 Ok(())
263 }
264
265 pub(crate) async fn screenshot(&self, args: ScreenshotArgs) -> ArcResult<Vec<u8>> {
266 let path = args.path.clone();
267 let v = send_message!(self, "screenshot", args);
268 let b64 = only_str(&v)?;
269 let bytes = base64::decode(b64).map_err(Error::InvalidBase64)?;
270 may_save(path.as_deref(), &bytes)?;
271 Ok(bytes)
272 }
273
274 pub(crate) async fn emulate_media(&self, args: EmulateMediaArgs) -> ArcResult<()> {
275 let _ = send_message!(self, "emulateMedia", args);
276 Ok(())
277 }
278
279 pub(crate) async fn opener(&self) -> ArcResult<Option<Weak<Page>>> {
280 let v = send_message!(self, "opener", Map::new());
281 let guid = match as_only_guid(&v) {
282 Some(g) => g,
283 None => return Ok(None)
284 };
285 let p = get_object!(self.context()?.lock().unwrap(), guid, Page)?;
286 Ok(Some(p))
287 }
288
289 pub(crate) async fn set_extra_http_headers<T>(&self, headers: T) -> ArcResult<()>
290 where
291 T: IntoIterator<Item = (String, String)>
292 {
293 #[derive(Serialize)]
294 #[serde(rename_all = "camelCase")]
295 struct Args {
296 headers: Vec<Header>
297 }
298 let args = Args {
299 headers: headers.into_iter().map(Header::from).collect()
300 };
301 let _ = send_message!(self, "setExtraHTTPHeaders", args);
302 Ok(())
303 }
304}
305
306impl Page {
308 pub(crate) fn viewport_size(&self) -> Option<Viewport> {
309 self.var.lock().unwrap().viewport.clone()
310 }
311
312 pub(crate) async fn set_viewport_size(&self, viewport_size: Viewport) -> ArcResult<()> {
313 #[derive(Debug, Serialize)]
314 #[serde(rename_all = "camelCase")]
315 struct Args {
316 viewport_size: Viewport
317 }
318 let args = Args {
319 viewport_size: viewport_size.clone()
320 };
321 let _ = send_message!(self, "setViewportSize", args);
322 self.var.lock().unwrap().viewport = Some(viewport_size);
323 Ok(())
324 }
325
326 pub(crate) fn frames(&self) -> Vec<Weak<Frame>> { self.var.lock().unwrap().frames.clone() }
327
328 pub(crate) fn default_timeout(&self) -> u32 {
329 let this = self.var.lock().unwrap().timeout;
330 let parent = || {
331 self.browser_context
332 .upgrade()
333 .map(|c| c.default_timeout())
334 .unwrap_or(Self::DEFAULT_TIMEOUT)
335 };
336 this.unwrap_or_else(parent)
337 }
338
339 pub(crate) fn default_navigation_timeout(&self) -> u32 {
340 let this = self.var.lock().unwrap().navigation_timeout;
341 let parent = || {
342 self.browser_context
343 .upgrade()
344 .map(|c| c.default_navigation_timeout())
345 .unwrap_or(Self::DEFAULT_TIMEOUT)
346 };
347 this.unwrap_or_else(parent)
348 }
349
350 pub(crate) async fn set_default_timeout(&self, timeout: u32) -> ArcResult<()> {
351 let mut args = Map::new();
352 args.insert("timeout".into(), timeout.into());
353 let _ = send_message!(self, "setDefaultTimeoutNoReply", args);
354 self.var.lock().unwrap().timeout = Some(timeout);
355 Ok(())
356 }
357
358 pub(crate) async fn set_default_navigation_timeout(&self, timeout: u32) -> ArcResult<()> {
359 let mut args = Map::new();
360 args.insert("timeout".into(), timeout.into());
361 let _ = send_message!(self, "setDefaultNavigationTimeoutNoReply", args);
362 self.var.lock().unwrap().navigation_timeout = Some(timeout);
363 Ok(())
364 }
365
366 pub(crate) fn on_frame_navigated(&self, f: Weak<Frame>) {
367 self.emit_event(Evt::FrameNavigated(f));
368 }
369
370 pub(crate) fn set_video(&self, video: Video) -> Result<(), Error> {
371 self.var.lock().unwrap().video = Some(video);
372 Ok(())
373 }
374
375 pub(crate) fn video(&self) -> Option<Video> { self.var.lock().unwrap().video.clone() }
376
377 fn on_close(&self, ctx: &Context) -> Result<(), Error> {
378 let bc = match self.browser_context().upgrade() {
379 None => return Ok(()),
380 Some(b) => b
381 };
382 let this = get_object!(ctx, self.guid(), Page)?;
383 bc.remove_page(&this);
384 self.emit_event(Evt::Close);
385 Ok(())
386 }
387
388 fn on_frame_attached(&self, ctx: &Context, guid: Str<Guid>) -> Result<(), Error> {
389 let this = get_object!(ctx, self.guid(), Page)?;
390 let f = get_object!(ctx, &guid, Frame)?;
391 upgrade(&f)?.set_page(this);
392 self.var.lock().unwrap().frames.push(f.clone());
393 self.emit_event(Evt::FrameAttached(f));
394 Ok(())
395 }
396
397 fn on_frame_detached(&self, ctx: &Context, guid: Str<Guid>) -> Result<(), Error> {
398 let frames = &mut self.var.lock().unwrap().frames;
399 *frames = frames
400 .iter()
401 .filter(|w| w.upgrade().map(|a| a.guid() != guid).unwrap_or(false))
402 .cloned()
403 .collect();
404 let f = get_object!(ctx, &guid, Frame)?;
405 self.emit_event(Evt::FrameDetached(f));
406 Ok(())
407 }
408
409 fn on_request_failed(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
410 #[derive(Debug, Deserialize)]
411 #[serde(rename_all = "camelCase")]
412 struct De {
413 request: OnlyGuid,
414 response_end_timing: f64,
415 failure_text: Option<String>
416 }
417 let De {
418 request: OnlyGuid { guid },
419 response_end_timing,
420 failure_text
421 } = serde_json::from_value(params.into())?;
422 let request = get_object!(ctx, &guid, Request)?;
423 let req = upgrade(&request)?;
424 req.set_failure(failure_text);
425 req.set_response_end(response_end_timing);
426 self.emit_event(Evt::RequestFailed(request));
427 Ok(())
428 }
429
430 fn on_request_finished(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
431 #[derive(Debug, Deserialize)]
432 #[serde(rename_all = "camelCase")]
433 struct De {
434 request: OnlyGuid,
435 response_end_timing: f64
436 }
437 let De {
438 request: OnlyGuid { guid },
439 response_end_timing
440 } = serde_json::from_value(params.into())?;
441 let request = get_object!(ctx, &guid, Request)?;
442 let req = upgrade(&request)?;
443 req.set_response_end(response_end_timing);
444 self.emit_event(Evt::RequestFinished(request));
445 Ok(())
446 }
447
448 pub(crate) fn workers(&self) -> Vec<Weak<Worker>> { self.var.lock().unwrap().workers.clone() }
449
450 fn push_worker(&self, worker: Weak<Worker>) { self.var.lock().unwrap().workers.push(worker); }
451
452 pub(crate) fn remove_worker(&self, worker: &Weak<Worker>) {
453 let workers = &mut self.var.lock().unwrap().workers;
454 workers.remove_one(|w| w.ptr_eq(worker));
455 }
456
457 fn on_worker(&self, ctx: &Context, worker: Weak<Worker>) -> Result<(), Error> {
458 self.push_worker(worker.clone());
459 let this = get_object!(ctx, self.guid(), Page)?;
460 upgrade(&worker)?.set_page(this);
461 self.emit_event(Evt::Worker(worker));
462 Ok(())
463 }
464
465 fn on_download(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
466 #[derive(Deserialize)]
467 #[serde(rename_all = "camelCase")]
468 struct De {
469 url: String,
470 suggested_filename: String,
471 artifact: OnlyGuid
472 }
473 let De {
474 url,
475 suggested_filename,
476 artifact: OnlyGuid { guid }
477 } = serde_json::from_value(params.into())?;
478 let artifact = get_object!(ctx, &guid, Artifact)?;
479 let download = Download::new(artifact, url, suggested_filename);
482 self.emit_event(Evt::Download(Arc::new(download)));
483 Ok(())
484 }
485
486 fn on_video(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
487 let v = params.into();
488 let guid = only_guid(&v)?;
489 let artifact = get_object!(ctx, guid, Artifact)?;
490 let video = Video::new(artifact);
491 self.set_video(video.clone())?;
492 self.emit_event(Evt::Video(video));
493 Ok(())
494 }
495
496 fn on_file_chooser(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
497 #[derive(Deserialize)]
498 #[serde(rename_all = "camelCase")]
499 struct De {
500 element: OnlyGuid,
501 is_multiple: bool
502 }
503 let De {
504 element: OnlyGuid { guid },
505 is_multiple
506 } = serde_json::from_value(params.into())?;
507 let element = get_object!(ctx, &guid, ElementHandle)?;
508 let this = get_object!(ctx, self.guid(), Page)?;
509 let file_chooser = FileChooser::new(this, element, is_multiple);
510 Ok(())
512 }
513}
514
515impl RemoteObject for Page {
516 fn channel(&self) -> &ChannelOwner { &self.channel }
517 fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
518
519 fn handle_event(
520 &self,
521 ctx: &Context,
522 method: Str<Method>,
523 params: Map<String, Value>
524 ) -> Result<(), Error> {
525 match method.as_str() {
526 "close" => self.on_close(ctx)?,
527 "frameattached" => {
528 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
529 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
530 self.on_frame_attached(ctx, guid)?;
531 }
532 "framedetached" => {
533 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
534 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
535 self.on_frame_detached(ctx, guid)?;
536 }
537 "load" => self.emit_event(Evt::Load),
538 "domcontentloaded" => self.emit_event(Evt::DomContentLoaded),
539 "crash" => self.emit_event(Evt::Crash),
540 "console" => {
541 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
542 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
543 let console = get_object!(ctx, &guid, ConsoleMessage)?;
544 self.emit_event(Evt::Console(console));
545 }
546 "request" => {
547 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
548 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
549 let request = get_object!(ctx, &guid, Request)?;
550 self.emit_event(Evt::Request(request));
551 }
552 "requestfailed" => self.on_request_failed(ctx, params)?,
553 "requestfinished" => self.on_request_finished(ctx, params)?,
554 "response" => {
555 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
556 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
557 let response = get_object!(ctx, &guid, Response)?;
558 self.emit_event(Evt::Response(response));
559 }
560 "popup" => {
561 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
562 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
563 let page = get_object!(ctx, &guid, Page)?;
564 self.emit_event(Evt::Popup(page));
565 }
566 "websocket" => {
567 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
568 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
569 let websocket = get_object!(ctx, &guid, WebSocket)?;
570 self.emit_event(Evt::WebSocket(websocket));
571 }
572 "worker" => {
573 let first = first_object(¶ms).ok_or(Error::InvalidParams)?;
574 let OnlyGuid { guid } = serde_json::from_value((*first).clone())?;
575 let worker = get_object!(ctx, &guid, Worker)?;
576 self.on_worker(ctx, worker)?;
577 }
578 "download" => self.on_download(ctx, params)?,
579 "video" => self.on_video(ctx, params)?,
580 "filechooser" => self.on_file_chooser(ctx, params)?,
581 _ => {}
582 }
583 Ok(())
584 }
585}
586
587#[derive(Debug, Clone)]
588pub(crate) enum Evt {
589 Close,
590 Crash,
591 Console(Weak<ConsoleMessage>),
592 Dialog,
594 Download(Arc<Download>),
595 DomContentLoaded,
598 PageError,
600 Request(Weak<Request>),
601 Response(Weak<Response>),
602 RequestFailed(Weak<Request>),
603 RequestFinished(Weak<Request>),
604 FrameAttached(Weak<Frame>),
605 FrameDetached(Weak<Frame>),
606 FrameNavigated(Weak<Frame>),
607 Load,
608 Popup(Weak<Page>),
609 WebSocket(Weak<WebSocket>),
610 Worker(Weak<Worker>),
611 Video(Video)
612}
613
614impl EventEmitter for Page {
615 type Event = Evt;
616 fn tx(&self) -> Option<broadcast::Sender<Self::Event>> { self.tx.lock().unwrap().clone() }
617 fn set_tx(&self, tx: broadcast::Sender<Self::Event>) { *self.tx.lock().unwrap() = Some(tx); }
618}
619
620#[derive(Debug, Clone, Copy, PartialEq)]
621pub enum EventType {
622 Close,
623 Crash,
624 Console,
625 Dialog,
626 Download,
627 DomContentLoaded,
629 PageError,
630 Request,
631 Response,
632 RequestFailed,
633 RequestFinished,
634 FrameAttached,
635 FrameDetached,
636 FrameNavigated,
637 Load,
638 Popup,
639 WebSocket,
640 Worker,
641 Video
642}
643
644impl IsEvent for Evt {
645 type EventType = EventType;
646
647 fn event_type(&self) -> Self::EventType {
648 match self {
649 Self::Close => EventType::Close,
650 Self::Crash => EventType::Crash,
651 Self::Console(_) => EventType::Console,
652 Self::Dialog => EventType::Dialog,
653 Self::Download(_) => EventType::Download,
654 Self::DomContentLoaded => EventType::DomContentLoaded,
656 Self::PageError => EventType::PageError,
657 Self::Request(_) => EventType::Request,
658 Self::Response(_) => EventType::Response,
659 Self::RequestFailed(_) => EventType::RequestFailed,
660 Self::RequestFinished(_) => EventType::RequestFinished,
661 Self::FrameAttached(_) => EventType::FrameAttached,
662 Self::FrameDetached(_) => EventType::FrameDetached,
663 Self::FrameNavigated(_) => EventType::FrameNavigated,
664 Self::Load => EventType::Load,
665 Self::Popup(_) => EventType::Popup,
666 Self::WebSocket(_) => EventType::WebSocket,
667 Self::Worker(_) => EventType::Worker,
668 Self::Video(_) => EventType::Video
669 }
670 }
671}
672
673#[derive(Deserialize)]
674#[serde(rename_all = "camelCase")]
675struct Initializer {
676 main_frame: OnlyGuid,
677 #[serde(rename = "viewportSize")]
678 viewport: Option<Viewport>
679}
680
681#[skip_serializing_none]
682#[derive(Serialize)]
683#[serde(rename_all = "camelCase")]
684pub(crate) struct MouseClickArgs {
685 x: f64,
686 y: f64,
687 pub(crate) delay: Option<f64>,
688 pub(crate) button: Option<MouseButton>,
689 pub(crate) click_count: Option<i32>
690}
691
692impl MouseClickArgs {
693 pub(crate) fn new(x: f64, y: f64) -> Self {
694 Self {
695 x,
696 y,
697 delay: None,
698 button: None,
699 click_count: None
700 }
701 }
702}
703
704#[skip_serializing_none]
705#[derive(Serialize, Default)]
706#[serde(rename_all = "camelCase")]
707pub(crate) struct AccessibilitySnapshotArgs {
708 pub(crate) interesting_only: Option<bool>,
709 pub(crate) root: Option<OnlyGuid>
710}
711
712#[derive(Debug, Deserialize, PartialEq)]
713#[serde(rename_all = "camelCase")]
714pub struct AccessibilitySnapshotResponse {
715 pub role: String,
716 pub name: String,
717 pub value: Option<Val>,
718 pub description: Option<String>,
719 pub keyshortcuts: Option<String>,
720 pub roledescription: Option<String>,
721 pub valuetext: Option<String>,
722 pub disabled: Option<bool>,
723 pub expanded: Option<bool>,
724 pub focused: Option<bool>,
725 pub modal: Option<bool>,
726 pub multiline: Option<bool>,
727 pub multiselectable: Option<bool>,
728 pub readonly: Option<bool>,
729 pub required: Option<bool>,
730 pub selected: Option<bool>,
731 pub checked: Option<Mixed>,
732 pub pressed: Option<Mixed>,
733 pub level: Option<i64>,
734 pub valuemin: Option<f64>,
735 pub valuemax: Option<f64>,
736 pub autocomplete: Option<String>,
737 pub haspopup: Option<String>,
738 pub invalid: Option<String>,
739 pub orientation: Option<String>,
740 #[serde(default)]
741 pub children: Vec<AccessibilitySnapshotResponse>
742}
743
744#[derive(Debug, Deserialize, PartialEq)]
745pub enum Val {
746 String(String),
747 Number(f64)
748}
749#[derive(Debug, Deserialize, PartialEq)]
750pub enum Mixed {
751 Mixed,
752 Bool(bool)
753}
754
755#[skip_serializing_none]
756#[derive(Serialize, Default)]
757#[serde(rename_all = "camelCase")]
758pub(crate) struct ReloadArgs {
759 pub(crate) timeout: Option<f64>,
760 pub(crate) wait_until: Option<DocumentLoadState>
761}
762
763#[skip_serializing_none]
764#[derive(Serialize, Default)]
765#[serde(rename_all = "camelCase")]
766pub(crate) struct PdfArgs<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j> {
767 pub(crate) scale: Option<f64>,
768 pub(crate) display_header_footer: Option<bool>,
769 pub(crate) header_template: Option<&'a str>,
770 pub(crate) footer_template: Option<&'b str>,
771 pub(crate) print_background: Option<bool>,
772 pub(crate) landscape: Option<bool>,
773 pub(crate) page_ranges: Option<&'c str>,
774 pub(crate) format: Option<&'d str>,
775 pub(crate) width: Option<Length<'e>>,
776 pub(crate) height: Option<Length<'f>>,
777 #[serde(rename = "preferCSSPageSize")]
778 pub(crate) prefer_css_page_size: Option<bool>,
779 pub(crate) margin: Option<PdfMargins<'g, 'h, 'i, 'j>>,
780 pub(crate) path: Option<PathBuf>
781}
782
783#[skip_serializing_none]
784#[derive(Serialize, Default)]
785#[serde(rename_all = "camelCase")]
786pub(crate) struct ScreenshotArgs {
787 pub(crate) timeout: Option<f64>,
788 pub(crate) r#type: Option<ScreenshotType>,
789 pub(crate) quality: Option<i32>,
790 pub(crate) omit_background: Option<bool>,
791 pub(crate) full_page: Option<bool>,
792 pub(crate) clip: Option<FloatRect>,
793 pub(crate) path: Option<PathBuf>
794}
795
796#[skip_serializing_none]
797#[derive(Serialize, Default)]
798#[serde(rename_all = "camelCase")]
799pub(crate) struct EmulateMediaArgs {
800 pub(crate) media: Option<Media>,
801 pub(crate) color_scheme: Option<ColorScheme>
802}
803
804#[derive(Serialize)]
805#[serde(rename_all = "lowercase")]
806pub enum Media {
807 Null,
809 Print,
810 Screen
811}