use std::fmt;
use std::sync::Arc;
use crate::error::{Error, Result};
use crate::identifiers::{FrameId, SessionId, TabId};
use crate::protocol::{Command, Request, Response};
use crate::browser::Window;
#[derive(Debug, Clone)]
pub struct FrameInfo {
pub frame_id: FrameId,
pub parent_frame_id: Option<FrameId>,
pub url: String,
}
pub(crate) struct TabInner {
pub tab_id: TabId,
pub frame_id: FrameId,
pub session_id: SessionId,
pub window: Option<Window>,
}
#[derive(Clone)]
pub struct Tab {
pub(crate) inner: Arc<TabInner>,
}
impl fmt::Debug for Tab {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Tab")
.field("tab_id", &self.inner.tab_id)
.field("frame_id", &self.inner.frame_id)
.field("session_id", &self.inner.session_id)
.finish_non_exhaustive()
}
}
impl Tab {
pub(crate) fn new(
tab_id: TabId,
frame_id: FrameId,
session_id: SessionId,
window: Option<Window>,
) -> Self {
Self {
inner: Arc::new(TabInner {
tab_id,
frame_id,
session_id,
window,
}),
}
}
}
impl Tab {
#[inline]
#[must_use]
pub fn tab_id(&self) -> TabId {
self.inner.tab_id
}
#[inline]
#[must_use]
pub fn frame_id(&self) -> FrameId {
self.inner.frame_id
}
#[inline]
#[must_use]
pub fn session_id(&self) -> SessionId {
self.inner.session_id
}
#[inline]
#[must_use]
pub fn is_main_frame(&self) -> bool {
self.inner.frame_id.is_main()
}
}
impl Tab {
pub(crate) async fn send_command(&self, command: Command) -> Result<Response> {
let window = self.get_window()?;
let request = Request::new(self.inner.tab_id, self.inner.frame_id, command);
window
.inner
.pool
.send(window.inner.session_id, request)
.await
}
pub(crate) fn get_window(&self) -> Result<&Window> {
self.inner
.window
.as_ref()
.ok_or_else(|| Error::protocol("Tab has no associated window"))
}
}
#[cfg(test)]
mod tests {
use super::Tab;
#[test]
fn test_tab_is_clone() {
fn assert_clone<T: Clone>() {}
assert_clone::<Tab>();
}
#[test]
fn test_tab_is_debug() {
fn assert_debug<T: std::fmt::Debug>() {}
assert_debug::<Tab>();
}
}