Skip to content

Commit

Permalink
Remove insaccessible history states
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrewster committed Apr 18, 2018
1 parent 087bd20 commit c08ad45
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 12 deletions.
54 changes: 42 additions & 12 deletions components/constellation/constellation.rs
Expand Up @@ -2490,15 +2490,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
Some(old_pipeline_id) => {
// Deactivate the old pipeline, and activate the new one.
let pipelines_to_close = if let Some(replace_reloader) = change.replace {
let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = change.replace {
let session_history = self.joint_session_histories
.entry(change.top_level_browsing_context_id).or_insert(JointSessionHistory::new());
session_history.replace(replace_reloader.clone(),
NeedsToReload::No(change.new_pipeline_id));

match replace_reloader {
NeedsToReload::No(pipeline_id) => vec![pipeline_id],
NeedsToReload::Yes(..) => vec![],
NeedsToReload::No(pipeline_id) => (Some(vec![pipeline_id]), None),
NeedsToReload::Yes(..) => (None, None),
}
} else {
let session_history = self.joint_session_histories
Expand All @@ -2509,20 +2509,50 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
old_reloader: NeedsToReload::No(old_pipeline_id),
};

session_history.push_diff(diff).into_iter()
.filter_map(|diff| match diff {
SessionHistoryDiff::BrowsingContextDiff { new_reloader, .. } => Some(new_reloader),
SessionHistoryDiff::PipelineDiff { .. } => None,
})
.filter_map(|pipeline_id| pipeline_id.alive_pipeline_id())
.collect::<Vec<_>>()
let mut pipelines_to_close = vec![];
let mut states_to_close = HashMap::new();

let diffs_to_close = session_history.push_diff(diff);

for diff in diffs_to_close {
match diff {
SessionHistoryDiff::BrowsingContextDiff { new_reloader, .. } => {
if let Some(pipeline_id) = new_reloader.alive_pipeline_id() {
pipelines_to_close.push(pipeline_id);
}
}
SessionHistoryDiff::PipelineDiff { pipeline_reloader, new_history_state_id, .. } => {
if let Some(pipeline_id) = pipeline_reloader.alive_pipeline_id() {
let states = states_to_close.entry(pipeline_id).or_insert(Vec::new());
states.push(new_history_state_id);
}
}
}
}

(Some(pipelines_to_close), Some(states_to_close))
};

self.update_activity(old_pipeline_id);
self.update_activity(change.new_pipeline_id);

for pipeline_id in pipelines_to_close {
self.close_pipeline(pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal);
if let Some(states_to_close) = states_to_close {
for (pipeline_id, states) in states_to_close {
let msg = ConstellationControlMsg::RemoveHistoryStates(pipeline_id, states);
let result = match self.pipelines.get(&pipeline_id) {
None => return warn!("Pipeline {} removed history states after closure", pipeline_id),
Some(pipeline) => pipeline.event_loop.send(msg),
};
if let Err(e) = result {
self.handle_send_error(pipeline_id, e);
}
}
}

if let Some(pipelines_to_close) = pipelines_to_close {
for pipeline_id in pipelines_to_close {
self.close_pipeline(pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal);
}
}

self.notify_history_changed(change.top_level_browsing_context_id);
Expand Down
6 changes: 6 additions & 0 deletions components/net/resource_thread.rs
Expand Up @@ -252,6 +252,12 @@ impl ResourceChannelManager {
let mut history_states = http_state.history_states.write().unwrap();
history_states.insert(history_state_id, history_state);
}
CoreResourceMsg::RemoveHistoryStates(states_to_remove) => {
let mut history_states = http_state.history_states.write().unwrap();
for history_state in states_to_remove {
history_states.remove(&history_state);
}
}
CoreResourceMsg::Synchronize(sender) => {
let _ = sender.send(());
}
Expand Down
2 changes: 2 additions & 0 deletions components/net_traits/lib.rs
Expand Up @@ -368,6 +368,8 @@ pub enum CoreResourceMsg {
GetHistoryState(HistoryStateId, IpcSender<Option<Vec<u8>>>),
/// Set a history state for a given history state id
SetHistoryState(HistoryStateId, Vec<u8>),
/// Removes history states for the given ids
RemoveHistoryStates(Vec<HistoryStateId>),
/// Synchronization message solely for knowing the state of the ResourceChannelManager loop
Synchronize(IpcSender<()>),
/// Send the network sender in constellation to CoreResourceThread
Expand Down
7 changes: 7 additions & 0 deletions components/script/dom/history.rs
Expand Up @@ -102,6 +102,13 @@ impl History {
}
}

pub fn remove_states(&self, states: Vec<HistoryStateId>) {
let _ = self.window
.upcast::<GlobalScope>()
.resource_threads()
.send(CoreResourceMsg::RemoveHistoryStates(states));
}

// https://html.spec.whatwg.org/multipage/#dom-history-pushstate
// https://html.spec.whatwg.org/multipage/#dom-history-replacestate
fn push_or_replace_state(&self,
Expand Down
10 changes: 10 additions & 0 deletions components/script/script_thread.rs
Expand Up @@ -1170,6 +1170,7 @@ impl ScriptThread {
PostMessage(id, ..) => Some(id),
UpdatePipelineId(_, _, id, _) => Some(id),
UpdateHistoryStateId(id, ..) => Some(id),
RemoveHistoryStates(id, ..) => Some(id),
FocusIFrame(id, ..) => Some(id),
WebDriverScriptCommand(id, ..) => Some(id),
TickAllAnimations(id) => Some(id),
Expand Down Expand Up @@ -1298,6 +1299,8 @@ impl ScriptThread {
reason),
ConstellationControlMsg::UpdateHistoryStateId(pipeline_id, history_state_id) =>
self.handle_update_history_state_id_msg(pipeline_id, history_state_id),
ConstellationControlMsg::RemoveHistoryStates(pipeline_id, history_states) =>
self.handle_remove_history_states(pipeline_id, history_states),
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
Expand Down Expand Up @@ -1683,6 +1686,13 @@ impl ScriptThread {
}
}

fn handle_remove_history_states(&self, pipeline_id: PipelineId, history_states: Vec<HistoryStateId>) {
match { self.documents.borrow().find_window(pipeline_id) } {
None => return warn!("update history state after pipeline {} closed.", pipeline_id),
Some(window) => window.History().r().remove_states(history_states),
}
}

/// Window was resized, but this script was not active, so don't reflow yet
fn handle_resize_inactive_msg(&self, id: PipelineId, new_size: WindowSizeData) {
let window = self.documents.borrow().find_window(id)
Expand Down
3 changes: 3 additions & 0 deletions components/script_traits/lib.rs
Expand Up @@ -291,6 +291,8 @@ pub enum ConstellationControlMsg {
UpdatePipelineId(PipelineId, BrowsingContextId, PipelineId, UpdatePipelineIdReason),
/// Updates the history state of a given pipeline.
UpdateHistoryStateId(PipelineId, Option<HistoryStateId>),
/// Removes inaccesible history states.
RemoveHistoryStates(PipelineId, Vec<HistoryStateId>),
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
/// PipelineId is for the parent, BrowsingContextId is for the nested browsing context
FocusIFrame(PipelineId, BrowsingContextId),
Expand Down Expand Up @@ -346,6 +348,7 @@ impl fmt::Debug for ConstellationControlMsg {
PostMessage(..) => "PostMessage",
UpdatePipelineId(..) => "UpdatePipelineId",
UpdateHistoryStateId(..) => "UpdateHistoryStateId",
RemoveHistoryStates(..) => "RemoveHistoryStates",
FocusIFrame(..) => "FocusIFrame",
WebDriverScriptCommand(..) => "WebDriverScriptCommand",
TickAllAnimations(..) => "TickAllAnimations",
Expand Down

0 comments on commit c08ad45

Please sign in to comment.