use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::RwLock;
use viewpoint_cdp::CdpConnection;
use viewpoint_cdp::protocol::runtime::ExecutionContextId;
use super::execution_context::{ExecutionContextRegistry, MAIN_WORLD_KEY};
#[derive(Debug, Clone)]
pub(super) struct FrameData {
pub url: String,
pub name: String,
pub detached: bool,
pub execution_contexts: HashMap<String, ExecutionContextId>,
}
#[derive(Debug)]
pub struct Frame {
pub(super) connection: Arc<CdpConnection>,
pub(super) session_id: String,
pub(super) id: String,
pub(super) parent_id: Option<String>,
pub(super) loader_id: String,
pub(super) data: RwLock<FrameData>,
pub(super) context_registry: Option<Arc<ExecutionContextRegistry>>,
pub(super) context_index: usize,
pub(super) page_index: usize,
pub(super) frame_index: usize,
}
impl Frame {
pub(crate) fn new(
connection: Arc<CdpConnection>,
session_id: String,
id: String,
parent_id: Option<String>,
loader_id: String,
url: String,
name: String,
) -> Self {
Self {
connection,
session_id,
id,
parent_id,
loader_id,
data: RwLock::new(FrameData {
url,
name,
detached: false,
execution_contexts: HashMap::new(),
}),
context_registry: None,
context_index: 0,
page_index: 0,
frame_index: 0,
}
}
pub(crate) fn new_with_indices(
connection: Arc<CdpConnection>,
session_id: String,
id: String,
parent_id: Option<String>,
loader_id: String,
url: String,
name: String,
context_index: usize,
page_index: usize,
frame_index: usize,
) -> Self {
Self {
connection,
session_id,
id,
parent_id,
loader_id,
data: RwLock::new(FrameData {
url,
name,
detached: false,
execution_contexts: HashMap::new(),
}),
context_registry: None,
context_index,
page_index,
frame_index,
}
}
pub(crate) fn with_context_registry(
connection: Arc<CdpConnection>,
session_id: String,
id: String,
parent_id: Option<String>,
loader_id: String,
url: String,
name: String,
context_registry: Arc<ExecutionContextRegistry>,
) -> Self {
Self {
connection,
session_id,
id,
parent_id,
loader_id,
data: RwLock::new(FrameData {
url,
name,
detached: false,
execution_contexts: HashMap::new(),
}),
context_registry: Some(context_registry),
context_index: 0,
page_index: 0,
frame_index: 0,
}
}
pub(crate) fn with_context_registry_and_indices(
connection: Arc<CdpConnection>,
session_id: String,
id: String,
parent_id: Option<String>,
loader_id: String,
url: String,
name: String,
context_registry: Arc<ExecutionContextRegistry>,
context_index: usize,
page_index: usize,
frame_index: usize,
) -> Self {
Self {
connection,
session_id,
id,
parent_id,
loader_id,
data: RwLock::new(FrameData {
url,
name,
detached: false,
execution_contexts: HashMap::new(),
}),
context_registry: Some(context_registry),
context_index,
page_index,
frame_index,
}
}
pub fn frame_index(&self) -> usize {
self.frame_index
}
pub fn id(&self) -> &str {
&self.id
}
pub fn parent_id(&self) -> Option<&str> {
self.parent_id.as_deref()
}
pub fn is_main(&self) -> bool {
self.parent_id.is_none()
}
pub fn loader_id(&self) -> &str {
&self.loader_id
}
pub fn url(&self) -> String {
self.data.read().url.clone()
}
pub fn name(&self) -> String {
self.data.read().name.clone()
}
pub fn is_detached(&self) -> bool {
self.data.read().detached
}
pub(crate) fn set_url(&self, url: String) {
self.data.write().url = url;
}
pub(crate) fn set_name(&self, name: String) {
self.data.write().name = name;
}
pub(crate) fn set_detached(&self) {
self.data.write().detached = true;
}
pub(crate) fn main_world_context_id(&self) -> Option<ExecutionContextId> {
if let Some(ref registry) = self.context_registry {
if let Some(context_id) = registry.main_world_context(&self.id) {
return Some(context_id);
}
}
self.data
.read()
.execution_contexts
.get(MAIN_WORLD_KEY)
.copied()
}
pub(crate) fn set_execution_context(&self, world_name: String, id: ExecutionContextId) {
self.data.write().execution_contexts.insert(world_name, id);
}
pub(crate) fn remove_execution_context(&self, id: ExecutionContextId) -> bool {
let mut data = self.data.write();
let original_len = data.execution_contexts.len();
data.execution_contexts
.retain(|_, &mut ctx_id| ctx_id != id);
data.execution_contexts.len() < original_len
}
pub(crate) fn clear_execution_contexts(&self) {
self.data.write().execution_contexts.clear();
}
pub(crate) fn session_id(&self) -> &str {
&self.session_id
}
pub(crate) fn connection(&self) -> &Arc<CdpConnection> {
&self.connection
}
}