use embedder_traits::ViewportDetails;
use log::warn;
use rustc_hash::{FxHashMap, FxHashSet};
use servo_base::id::{BrowsingContextGroupId, BrowsingContextId, PipelineId, WebViewId};
use crate::pipeline::Pipeline;
#[derive(Debug)]
pub struct NewBrowsingContextInfo {
pub parent_pipeline_id: Option<PipelineId>,
pub is_private: bool,
pub inherited_secure_context: Option<bool>,
pub throttled: bool,
}
pub struct BrowsingContext {
pub bc_group_id: BrowsingContextGroupId,
pub id: BrowsingContextId,
pub webview_id: WebViewId,
pub viewport_details: ViewportDetails,
pub is_private: bool,
pub inherited_secure_context: Option<bool>,
pub throttled: bool,
pub pipeline_id: PipelineId,
pub parent_pipeline_id: Option<PipelineId>,
pub pipelines: FxHashSet<PipelineId>,
}
impl BrowsingContext {
#[expect(clippy::too_many_arguments)]
pub fn new(
bc_group_id: BrowsingContextGroupId,
id: BrowsingContextId,
webview_id: WebViewId,
pipeline_id: PipelineId,
parent_pipeline_id: Option<PipelineId>,
viewport_details: ViewportDetails,
is_private: bool,
inherited_secure_context: Option<bool>,
throttled: bool,
) -> BrowsingContext {
let mut pipelines = FxHashSet::default();
pipelines.insert(pipeline_id);
BrowsingContext {
bc_group_id,
id,
webview_id,
viewport_details,
is_private,
inherited_secure_context,
throttled,
pipeline_id,
parent_pipeline_id,
pipelines,
}
}
pub fn update_current_entry(&mut self, pipeline_id: PipelineId) {
self.pipeline_id = pipeline_id;
}
pub fn is_top_level(&self) -> bool {
self.id == self.webview_id
}
}
pub struct FullyActiveBrowsingContextsIterator<'a> {
pub stack: Vec<BrowsingContextId>,
pub browsing_contexts: &'a FxHashMap<BrowsingContextId, BrowsingContext>,
pub pipelines: &'a FxHashMap<PipelineId, Pipeline>,
}
impl<'a> Iterator for FullyActiveBrowsingContextsIterator<'a> {
type Item = &'a BrowsingContext;
fn next(&mut self) -> Option<&'a BrowsingContext> {
loop {
let browsing_context_id = self.stack.pop()?;
let browsing_context = match self.browsing_contexts.get(&browsing_context_id) {
Some(browsing_context) => browsing_context,
None => {
warn!(
"BrowsingContext {:?} iterated after closure.",
browsing_context_id
);
continue;
},
};
let pipeline = match self.pipelines.get(&browsing_context.pipeline_id) {
Some(pipeline) => pipeline,
None => {
warn!(
"Pipeline {:?} iterated after closure.",
browsing_context.pipeline_id
);
continue;
},
};
self.stack.extend(pipeline.children.iter());
return Some(browsing_context);
}
}
}
pub struct AllBrowsingContextsIterator<'a> {
pub stack: Vec<BrowsingContextId>,
pub browsing_contexts: &'a FxHashMap<BrowsingContextId, BrowsingContext>,
pub pipelines: &'a FxHashMap<PipelineId, Pipeline>,
}
impl<'a> Iterator for AllBrowsingContextsIterator<'a> {
type Item = &'a BrowsingContext;
fn next(&mut self) -> Option<&'a BrowsingContext> {
let pipelines = self.pipelines;
loop {
let browsing_context_id = self.stack.pop()?;
let browsing_context = match self.browsing_contexts.get(&browsing_context_id) {
Some(browsing_context) => browsing_context,
None => {
warn!(
"BrowsingContext {:?} iterated after closure.",
browsing_context_id
);
continue;
},
};
let child_browsing_context_ids = browsing_context
.pipelines
.iter()
.filter_map(|pipeline_id| pipelines.get(pipeline_id))
.flat_map(|pipeline| pipeline.children.iter());
self.stack.extend(child_browsing_context_ids);
return Some(browsing_context);
}
}
}