Skip to content

Commit

Permalink
Add browsers map to Constellation for per browser bookkeeping
Browse files Browse the repository at this point in the history
  • Loading branch information
vimpunk committed Nov 2, 2018
1 parent 83418ff commit 7be7f18
Showing 1 changed file with 85 additions and 56 deletions.
141 changes: 85 additions & 56 deletions components/constellation/constellation.rs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ use timer_scheduler::TimerScheduler;
use webrender_api; use webrender_api;
use webvr_traits::{WebVREvent, WebVRMsg}; use webvr_traits::{WebVREvent, WebVRMsg};


/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
/// store browser specific data for bookkeeping.
struct Browser {
/// The currently focused browsing context for key events. The focused
/// pipeline is the current entry of the focused browsing context.
focused_browsing_context_id: BrowsingContextId,

/// The joint session history for this browser.
session_history: JointSessionHistory,
}

/// The `Constellation` itself. In the servo browser, there is one /// The `Constellation` itself. In the servo browser, there is one
/// constellation, which maintains all of the browser global data. /// constellation, which maintains all of the browser global data.
/// In embedded applications, there may be more than one constellation, /// In embedded applications, there may be more than one constellation,
Expand Down Expand Up @@ -201,16 +212,21 @@ pub struct Constellation<Message, LTF, STF> {
/// constellation to send messages to the compositor thread. /// constellation to send messages to the compositor thread.
compositor_proxy: CompositorProxy, compositor_proxy: CompositorProxy,


/// The last frame tree sent to WebRender. /// The last frame tree sent to WebRender, denoting the browser (tab) user
/// has currently selected. This also serves as a key to the retrieve data
/// about the current active browser from the `browsers` hash map.
active_browser_id: Option<TopLevelBrowsingContextId>, active_browser_id: Option<TopLevelBrowsingContextId>,


/// All the browsers in constellation. Since the active browser /// All the browsers in constellation.
/// (`active_browser_id`) may change with the `SelectBrowser` message (e.g. ///
/// when user switches to another tab), we must keep track of each browser's /// TODO: update docs
/// focused browsing context so that we can restore the ///
/// `focused_browsing_context_id` to point to the active browser's focused /// Since the active browser (`active_browser_id`) may change with the
/// browsing context. /// `SelectBrowser` message (e.g. when user switches to another tab), we
browser_ids: HashMap<TopLevelBrowsingContextId, BrowsingContextId>, /// must keep track of each browser's focused browsing context so that we
/// can restore the `focused_browsing_context_id` to point to the active
/// browser's focused browsing context.
browsers: HashMap<TopLevelBrowsingContextId, Browser>,


/// The currently focused browsing context for key events. The focused /// The currently focused browsing context for key events. The focused
/// pipeline is the current entry of the focused browsing context. This /// pipeline is the current entry of the focused browsing context. This
Expand Down Expand Up @@ -287,10 +303,8 @@ pub struct Constellation<Message, LTF, STF> {
/// to become same-origin, at which point they can share DOM objects. /// to become same-origin, at which point they can share DOM objects.
event_loops: HashMap<Host, Weak<EventLoop>>, event_loops: HashMap<Host, Weak<EventLoop>>,


joint_session_histories: HashMap<TopLevelBrowsingContextId, JointSessionHistory>, /// The set of all the pipelines in the browser. (See the `pipeline` module

/// for more details.)
/// The set of all the pipelines in the browser.
/// (See the `pipeline` module for more details.)
pipelines: HashMap<PipelineId, Pipeline>, pipelines: HashMap<PipelineId, Pipeline>,


/// The set of all the browsing contexts in the browser. /// The set of all the browsing contexts in the browser.
Expand Down Expand Up @@ -600,7 +614,7 @@ where
embedder_proxy: state.embedder_proxy, embedder_proxy: state.embedder_proxy,
compositor_proxy: state.compositor_proxy, compositor_proxy: state.compositor_proxy,
active_browser_id: None, active_browser_id: None,
browser_ids: HashMap::new(), browsers: HashMap::new(),
focused_browsing_context_id: None, focused_browsing_context_id: None,
debugger_chan: state.debugger_chan, debugger_chan: state.debugger_chan,
devtools_chan: state.devtools_chan, devtools_chan: state.devtools_chan,
Expand All @@ -612,7 +626,6 @@ where
swmanager_receiver: swmanager_receiver, swmanager_receiver: swmanager_receiver,
swmanager_sender: sw_mgr_clone, swmanager_sender: sw_mgr_clone,
event_loops: HashMap::new(), event_loops: HashMap::new(),
joint_session_histories: HashMap::new(),
pipelines: HashMap::new(), pipelines: HashMap::new(),
browsing_contexts: HashMap::new(), browsing_contexts: HashMap::new(),
pending_changes: vec![], pending_changes: vec![],
Expand Down Expand Up @@ -1657,13 +1670,14 @@ where


// Register this new top-level browsing context id as a browser and set // Register this new top-level browsing context id as a browser and set
// its focused browsing context to be itself. // its focused browsing context to be itself.
self.browser_ids.insert(top_level_browsing_context_id, browsing_context_id); self.browsers.insert(top_level_browsing_context_id, Browser {
focused_browsing_context_id: browsing_context_id,
session_history: JointSessionHistory::new(),
});
if self.focused_browsing_context_id.is_none() { if self.focused_browsing_context_id.is_none() {
self.focused_browsing_context_id = Some(browsing_context_id); self.focused_browsing_context_id = Some(browsing_context_id);
} }


self.joint_session_histories
.insert(top_level_browsing_context_id, JointSessionHistory::new());
self.new_pipeline( self.new_pipeline(
pipeline_id, pipeline_id,
browsing_context_id, browsing_context_id,
Expand Down Expand Up @@ -1695,7 +1709,7 @@ where
) { ) {
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal);
self.browser_ids.remove(&top_level_browsing_context_id); self.browsers.remove(&top_level_browsing_context_id);
if self.active_browser_id == Some(top_level_browsing_context_id) { if self.active_browser_id == Some(top_level_browsing_context_id) {
self.focused_browsing_context_id = None; self.focused_browsing_context_id = None;
self.active_browser_id = None; self.active_browser_id = None;
Expand Down Expand Up @@ -1979,7 +1993,10 @@ where


assert!(!self.pipelines.contains_key(&new_pipeline_id)); assert!(!self.pipelines.contains_key(&new_pipeline_id));
self.pipelines.insert(new_pipeline_id, pipeline); self.pipelines.insert(new_pipeline_id, pipeline);
self.joint_session_histories.insert(new_top_level_browsing_context_id, JointSessionHistory::new()); self.browsers.insert(new_top_level_browsing_context_id, Browser {
focused_browsing_context_id: new_browsing_context_id,
session_history: JointSessionHistory::new(),
});
self.add_pending_change(SessionHistoryChange { self.add_pending_change(SessionHistoryChange {
top_level_browsing_context_id: new_top_level_browsing_context_id, top_level_browsing_context_id: new_top_level_browsing_context_id,
browsing_context_id: new_browsing_context_id, browsing_context_id: new_browsing_context_id,
Expand Down Expand Up @@ -2571,9 +2588,9 @@ where
sender: IpcSender<u32>, sender: IpcSender<u32>,
) { ) {
let length = self let length = self
.joint_session_histories .browsers
.get(&top_level_browsing_context_id) .get(&top_level_browsing_context_id)
.map(JointSessionHistory::history_length) .map(|browser| browser.session_history.history_length())
.unwrap_or(1); .unwrap_or(1);
let _ = sender.send(length as u32); let _ = sender.send(length as u32);
} }
Expand Down Expand Up @@ -2770,11 +2787,18 @@ where
} }


// But we always need to update the focused browsing context in its // But we always need to update the focused browsing context in its
// browser in `browser_ids`. However, there is an opportunity to avoid // browser in `browsers`. However, there is an opportunity to avoid the
// the look up if the focus request targets an already focused browsing // look up if the focus request targets an already focused browsing
// context. // context.
if Some(browsing_context_id) != self.focused_browsing_context_id { if Some(browsing_context_id) != self.focused_browsing_context_id {
self.browser_ids.insert(top_level_browsing_context_id, browsing_context_id); let browser = match self.browsers.get_mut(&top_level_browsing_context_id) {
Some(browser) => browser,
None => return warn!(
"Browser {} for focus msg does not exist",
top_level_browsing_context_id
),
};
browser.focused_browsing_context_id = browsing_context_id;
} }


// Focus parent iframes recursively // Focus parent iframes recursively
Expand Down Expand Up @@ -3000,11 +3024,8 @@ where
// LoadData of inner frames are ignored and replaced with the LoadData // LoadData of inner frames are ignored and replaced with the LoadData
// of the parent. // of the parent.


let session_history = match self let session_history = match self.browsers.get(&top_level_browsing_context_id) {
.joint_session_histories Some(browser) => &browser.session_history,
.get(&top_level_browsing_context_id)
{
Some(session_history) => session_history,
None => { None => {
return warn!( return warn!(
"Session history does not exist for {}", "Session history does not exist for {}",
Expand Down Expand Up @@ -3199,24 +3220,17 @@ where
let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) =
change.replace change.replace
{ {
let session_history = self self.get_joint_session_history(change.top_level_browsing_context_id)
.joint_session_histories .replace_reloader(
.entry(change.top_level_browsing_context_id) replace_reloader.clone(),
.or_insert(JointSessionHistory::new()); NeedsToReload::No(change.new_pipeline_id),
session_history.replace_reloader( );
replace_reloader.clone(),
NeedsToReload::No(change.new_pipeline_id),
);


match replace_reloader { match replace_reloader {
NeedsToReload::No(pipeline_id) => (Some(vec![pipeline_id]), None), NeedsToReload::No(pipeline_id) => (Some(vec![pipeline_id]), None),
NeedsToReload::Yes(..) => (None, None), NeedsToReload::Yes(..) => (None, None),
} }
} else { } else {
let session_history = self
.joint_session_histories
.entry(change.top_level_browsing_context_id)
.or_insert(JointSessionHistory::new());
let diff = SessionHistoryDiff::BrowsingContextDiff { let diff = SessionHistoryDiff::BrowsingContextDiff {
browsing_context_id: change.browsing_context_id, browsing_context_id: change.browsing_context_id,
new_reloader: NeedsToReload::No(change.new_pipeline_id), new_reloader: NeedsToReload::No(change.new_pipeline_id),
Expand All @@ -3226,7 +3240,9 @@ where
let mut pipelines_to_close = vec![]; let mut pipelines_to_close = vec![];
let mut states_to_close = HashMap::new(); let mut states_to_close = HashMap::new();


let diffs_to_close = session_history.push_diff(diff); let diffs_to_close = self
.get_joint_session_history(change.top_level_browsing_context_id)
.push_diff(diff);


for diff in diffs_to_close { for diff in diffs_to_close {
match diff { match diff {
Expand Down Expand Up @@ -3749,17 +3765,23 @@ where
top_level_browsing_context_id: TopLevelBrowsingContextId, top_level_browsing_context_id: TopLevelBrowsingContextId,
pipeline_id: PipelineId, pipeline_id: PipelineId,
) { ) {
let load_data = match self.pipelines.get(&pipeline_id) { match self.browsers.get_mut(&top_level_browsing_context_id) {
Some(pipeline) => pipeline.load_data.clone(), Some(browser) => {
None => return, let load_data = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.load_data.clone(),
None => return warn!("Discarding closed pipeline {}", pipeline_id),
};
browser.session_history.replace_reloader(
NeedsToReload::No(pipeline_id),
NeedsToReload::Yes(pipeline_id, load_data),
);
},
None => return warn!(
"Discarding pipeline {} after browser {} closure",
pipeline_id,
top_level_browsing_context_id,
),
}; };
self.joint_session_histories
.entry(top_level_browsing_context_id)
.or_insert(JointSessionHistory::new())
.replace_reloader(
NeedsToReload::No(pipeline_id),
NeedsToReload::Yes(pipeline_id, load_data),
);
self.close_pipeline( self.close_pipeline(
pipeline_id, pipeline_id,
DiscardBrowsingContext::No, DiscardBrowsingContext::No,
Expand Down Expand Up @@ -3878,9 +3900,16 @@ where
&mut self, &mut self,
top_level_id: TopLevelBrowsingContextId, top_level_id: TopLevelBrowsingContextId,
) -> &mut JointSessionHistory { ) -> &mut JointSessionHistory {
self.joint_session_histories &mut self.browsers
.entry(top_level_id) .entry(top_level_id)
.or_insert(JointSessionHistory::new()) // This shouldn't be necessary since `get_joint_session_history` is
// invoked for existing browsers but we need this to satisfy the
// type system.
.or_insert_with(|| Browser {
focused_browsing_context_id: BrowsingContextId::from(top_level_id),
session_history: JointSessionHistory::new(),
})
.session_history
} }


// Convert a browsing context to a sendable form to pass to the compositor // Convert a browsing context to a sendable form to pass to the compositor
Expand Down Expand Up @@ -3937,9 +3966,9 @@ where
// `send_frame_tree`). // `send_frame_tree`).
if Some(top_level_browsing_context_id) != self.active_browser_id { if Some(top_level_browsing_context_id) != self.active_browser_id {
self.active_browser_id = Some(top_level_browsing_context_id); self.active_browser_id = Some(top_level_browsing_context_id);
self.focused_browsing_context_id = self.browser_ids self.focused_browsing_context_id = self.browsers
.get(&top_level_browsing_context_id) .get(&top_level_browsing_context_id)
.map(|focus_id| *focus_id) .map(|browser| browser.focused_browsing_context_id)
.or(Some(browsing_context_id)); .or(Some(browsing_context_id));
} }


Expand Down

0 comments on commit 7be7f18

Please sign in to comment.