"javascript:" urls: clean up after aborting a page load

Problem:
  After aborting on a 204 or 205 status code, you could no longer
  follow links on the page.

Cause:
  `constellation.rs` ignores new LoadUrl requests since the aborted
  one is in its `pending_changes` list.

Solution:
  Send a message to constellation that lets it clean up its
  `pending_changes` list.
This commit is contained in:
Daniel Johnson 2017-08-27 21:42:14 -07:00
parent af41769d70
commit ff786a050a
3 changed files with 22 additions and 4 deletions

View file

@ -1055,6 +1055,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
debug!("constellation got URL load message from script"); debug!("constellation got URL load message from script");
self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace); self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace);
} }
FromScriptMsg::AbortLoadUrl => {
debug!("constellation got URL load message from script");
self.handle_abort_load_url_msg(source_pipeline_id);
}
// A page loaded has completed all parsing, script, and reflow messages have been sent. // A page loaded has completed all parsing, script, and reflow messages have been sent.
FromScriptMsg::LoadComplete => { FromScriptMsg::LoadComplete => {
debug!("constellation got load complete message"); debug!("constellation got load complete message");
@ -1874,6 +1878,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
} }
} }
fn handle_abort_load_url_msg(&mut self, new_pipeline_id: PipelineId) {
let pending_index = self.pending_changes.iter().rposition(|change| {
change.new_pipeline_id == new_pipeline_id
});
// If it is found, remove it from the pending changes.
if let Some(pending_index) = pending_index {
self.pending_changes.remove(pending_index);
self.close_pipeline(new_pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal);
}
}
fn handle_load_start_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, fn handle_load_start_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId,
pipeline_id: PipelineId) { pipeline_id: PipelineId) {
if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() { if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() {

View file

@ -1676,19 +1676,19 @@ impl ScriptThread {
// the pipeline exited before the page load completed. // the pipeline exited before the page load completed.
match idx { match idx {
Some(idx) => { Some(idx) => {
let load = self.incomplete_loads.borrow_mut().remove(idx);
// https://html.spec.whatwg.org/multipage/#process-a-navigate-response // https://html.spec.whatwg.org/multipage/#process-a-navigate-response
// 2. If response's status is 204 or 205, then abort these steps. // 2. If response's status is 204 or 205, then abort these steps.
match metadata { match metadata {
Some(Metadata { status: Some((204 ... 205, _)), .. }) => { Some(Metadata { status: Some((204 ... 205, _)), .. }) => {
// TODO: This leaves the page in a broken state where you can't follow self.script_sender
// other links. Fix this. .send((id.clone(), ScriptMsg::AbortLoadUrl))
.unwrap();
return None; return None;
}, },
_ => () _ => ()
}; };
let load = self.incomplete_loads.borrow_mut().remove(idx);
metadata.map(|meta| self.load(meta, load)) metadata.map(|meta| self.load(meta, load))
} }
None => { None => {

View file

@ -99,6 +99,8 @@ pub enum ScriptMsg {
/// A new load has been requested, with an option to replace the current entry once loaded /// A new load has been requested, with an option to replace the current entry once loaded
/// instead of adding a new entry. /// instead of adding a new entry.
LoadUrl(LoadData, bool), LoadUrl(LoadData, bool),
/// Abort loading after sending a LoadUrl message.
AbortLoadUrl,
/// Post a message to the currently active window of a given browsing context. /// Post a message to the currently active window of a given browsing context.
PostMessage(BrowsingContextId, Option<ImmutableOrigin>, Vec<u8>), PostMessage(BrowsingContextId, Option<ImmutableOrigin>, Vec<u8>),
/// Dispatch a mozbrowser event to the parent of a mozbrowser iframe. /// Dispatch a mozbrowser event to the parent of a mozbrowser iframe.