1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
pub use crate::imp::browser_context::EventType;
use crate::{
    api::{Browser, Page},
    imp::{
        browser_context::{BrowserContext as Impl, Evt},
        core::*,
        prelude::*,
        utils::{Cookie, Geolocation, StorageState}
    },
    Error
};

pub struct BrowserContext {
    inner: Weak<Impl>
}

impl BrowserContext {
    pub(crate) fn new(inner: Weak<Impl>) -> Self { Self { inner } }

    pub fn pages(&self) -> Result<Vec<Page>, Error> {
        Ok(upgrade(&self.inner)?
            .pages()
            .iter()
            .cloned()
            .map(Page::new)
            .collect())
    }

    ///// Returns the browser instance of the context. If it was launched as a persistent context None gets returned.
    pub fn browser(&self) -> Result<Option<Browser>, Error> {
        Ok(upgrade(&self.inner)?.browser().map(Browser::new))
    }

    pub async fn new_page(&self) -> Result<Page, Arc<Error>> {
        let inner = upgrade(&self.inner)?;
        Ok(Page::new(inner.new_page().await?))
    }

    pub async fn set_default_navigation_timeout(&self, timeout: u32) -> ArcResult<()> {
        upgrade(&self.inner)?
            .set_default_navigation_timeout(timeout)
            .await
    }

    pub async fn set_default_timeout(&self, timeout: u32) -> ArcResult<()> {
        upgrade(&self.inner)?.set_default_timeout(timeout).await
    }

    pub async fn cookies(&self, urls: &[String]) -> ArcResult<Vec<Cookie>> {
        upgrade(&self.inner)?.cookies(urls).await
    }

    pub async fn add_cookies(&self, cookies: &[Cookie]) -> ArcResult<()> {
        upgrade(&self.inner)?.add_cookies(cookies).await
    }

    pub async fn clear_cookies(&self) -> ArcResult<()> {
        upgrade(&self.inner)?.clear_cookies().await
    }

    pub async fn grant_permission(
        &self,
        permissions: &[String],
        origin: Option<&str>
    ) -> ArcResult<()> {
        upgrade(&self.inner)?
            .grant_permission(permissions, origin)
            .await
    }

    pub async fn clear_permissions(&self) -> ArcResult<()> {
        upgrade(&self.inner)?.clear_permissions().await
    }

    pub async fn set_geolocation(&self, geolocation: Option<&Geolocation>) -> ArcResult<()> {
        upgrade(&self.inner)?.set_geolocation(geolocation).await
    }

    pub async fn set_offline(&self, offline: bool) -> ArcResult<()> {
        upgrade(&self.inner)?.set_offline(offline).await
    }

    pub async fn add_init_script(&self, script: &str) -> ArcResult<()> {
        upgrade(&self.inner)?.add_init_script(script).await
    }

    pub async fn set_extra_http_headers<T>(&self, headers: T) -> ArcResult<()>
    where
        T: IntoIterator<Item = (String, String)>
    {
        upgrade(&self.inner)?.set_extra_http_headers(headers).await
    }

    // async fn expose_binding(&mut self) -> Result<(), Error> { unimplemented!() }

    // async fn expose_function(&mut self) -> Result<(), Error> { unimplemented!() }

    // async fn route(&mut self) -> Result<(), Error> { unimplemented!() }

    // async fn unroute(&mut self) -> Result<(), Error> { unimplemented!() }

    pub async fn expect_event(&self, evt: EventType) -> Result<Event, Error> {
        upgrade(&self.inner)?
            .expect_event(evt)
            .await
            .map(Event::from)
    }

    // pub fn subscribe_event(&self) -> Result<broadcast::Receiver<Event>, Error> {
    //    Ok(upgrade(&self.inner)?.subscribe_event())
    //}

    pub async fn storage_state(&self) -> ArcResult<StorageState> {
        upgrade(&self.inner)?.storage_state().await
    }

    /// All temporary browsers will be closed when the connection is terminated, but
    /// this struct has no Drop. it needs to be called explicitly to close it at any given time.
    pub async fn close(&self) -> ArcResult<()> {
        let inner = match self.inner.upgrade() {
            None => return Ok(()),
            Some(inner) => inner
        };
        inner.close().await
    }

    pub async fn pause(&self) -> ArcResult<()> { upgrade(&self.inner)?.pause().await }
}

pub enum Event {
    Close,
    Page(Page)
}

impl From<Evt> for Event {
    fn from(e: Evt) -> Event {
        match e {
            Evt::Close => Event::Close,
            Evt::Page(w) => Event::Page(Page::new(w))
        }
    }
}