diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index e35ad261864..fa58b1f7aed 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1055,6 +1055,10 @@ impl Constellation debug!("constellation got URL load message from script"); 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. FromScriptMsg::LoadComplete => { debug!("constellation got load complete message"); @@ -1874,6 +1878,18 @@ impl Constellation } } + 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, pipeline_id: PipelineId) { if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() { diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e234805f0b6..dc19687fb06 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1676,19 +1676,19 @@ impl ScriptThread { // the pipeline exited before the page load completed. match idx { Some(idx) => { - let load = self.incomplete_loads.borrow_mut().remove(idx); - // https://html.spec.whatwg.org/multipage/#process-a-navigate-response // 2. If response's status is 204 or 205, then abort these steps. match metadata { Some(Metadata { status: Some((204 ... 205, _)), .. }) => { - // TODO: This leaves the page in a broken state where you can't follow - // other links. Fix this. + self.script_sender + .send((id.clone(), ScriptMsg::AbortLoadUrl)) + .unwrap(); return None; }, _ => () }; + let load = self.incomplete_loads.borrow_mut().remove(idx); metadata.map(|meta| self.load(meta, load)) } None => { diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 2d449e986a4..b4293230d14 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -99,6 +99,8 @@ pub enum ScriptMsg { /// A new load has been requested, with an option to replace the current entry once loaded /// instead of adding a new entry. LoadUrl(LoadData, bool), + /// Abort loading after sending a LoadUrl message. + AbortLoadUrl, /// Post a message to the currently active window of a given browsing context. PostMessage(BrowsingContextId, Option, Vec), /// Dispatch a mozbrowser event to the parent of a mozbrowser iframe.