Skip to main content

chromiumoxide/handler/
httpfuture.rs

1use futures_util::future::{Fuse, FusedFuture};
2use futures_util::FutureExt;
3use pin_project_lite::pin_project;
4use std::future::Future;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7use tokio::sync::mpsc;
8
9use crate::handler::commandfuture::CommandFuture;
10use crate::handler::target::TargetMessage;
11use crate::handler::target_message_future::TargetMessageFuture;
12use crate::{ArcHttpRequest, Result};
13use chromiumoxide_types::Command;
14
15type ArcRequest = ArcHttpRequest;
16
17pin_project! {
18    pub struct HttpFuture<T: Command> {
19        #[pin]
20        command: Fuse<CommandFuture<T>>,
21        #[pin]
22        navigation: TargetMessageFuture<ArcHttpRequest>,
23    }
24}
25
26impl<T: Command> HttpFuture<T> {
27    pub fn new(
28        sender: mpsc::Sender<TargetMessage>,
29        command: CommandFuture<T>,
30        request_timeout: std::time::Duration,
31    ) -> Self {
32        Self {
33            command: command.fuse(),
34            navigation: TargetMessageFuture::<T>::wait_for_navigation(sender, request_timeout),
35        }
36    }
37}
38
39impl<T> Future for HttpFuture<T>
40where
41    T: Command,
42{
43    type Output = Result<ArcRequest>;
44
45    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
46        let this = self.project();
47
48        // 1. First complete command request future
49        // 2. Switch polls navigation
50        if this.command.is_terminated() {
51            this.navigation.poll(cx)
52        } else {
53            match this.command.poll(cx) {
54                Poll::Ready(Ok(_command_response)) => {
55                    // Command succeeded — reset the navigation timer so it
56                    // gets a full request_timeout from NOW, not from when
57                    // HttpFuture was constructed.
58                    this.navigation.reset_deadline();
59                    cx.waker().wake_by_ref();
60                    Poll::Pending
61                }
62                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
63                Poll::Pending => Poll::Pending,
64            }
65        }
66    }
67}