diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 0e65c36ecf3..3cd67edcbcd 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -873,6 +873,9 @@ impl Constellation let window_size = self.pipelines.get(&failure.pipeline_id).and_then(|pipeline| pipeline.size); + // Notify the browser chrome that the pipeline has failed + self.trigger_mozbrowsererror(failure.pipeline_id); + self.close_pipeline(failure.pipeline_id, ExitPipelineMode::Force); while let Some(pending_pipeline_id) = self.pending_frames.iter().find(|pending| { @@ -1916,30 +1919,54 @@ impl Constellation } // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange + // Note that this is a no-op if the pipeline is not an immediate child iframe of the root fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) { - if prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { - let event_info = self.pipelines.get(&pipeline_id).and_then(|pipeline| { - pipeline.parent_info.map(|(containing_pipeline_id, subpage_id)| { - (containing_pipeline_id, subpage_id, pipeline.url.serialize()) - }) - }); + if !prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { return; } - // If this is an iframe, then send the event with new url - if let Some((containing_pipeline_id, subpage_id, url)) = event_info { - if let Some(parent_pipeline) = self.pipelines.get(&containing_pipeline_id) { - if let Some(frame_id) = self.pipeline_to_frame_map.get(&pipeline_id) { - if let Some(frame) = self.frames.get(&frame_id) { - let can_go_backward = !frame.prev.is_empty(); - let can_go_forward = !frame.next.is_empty(); - let event = MozBrowserEvent::LocationChange(url, can_go_backward, can_go_forward); - parent_pipeline.trigger_mozbrowser_event(subpage_id, event); - } + let event_info = self.pipelines.get(&pipeline_id).and_then(|pipeline| { + pipeline.parent_info.map(|(containing_pipeline_id, subpage_id)| { + (containing_pipeline_id, subpage_id, pipeline.url.serialize()) + }) + }); + + // If this is an iframe, then send the event with new url + if let Some((containing_pipeline_id, subpage_id, url)) = event_info { + if let Some(parent_pipeline) = self.pipelines.get(&containing_pipeline_id) { + if let Some(frame_id) = self.pipeline_to_frame_map.get(&pipeline_id) { + if let Some(frame) = self.frames.get(&frame_id) { + let can_go_backward = !frame.prev.is_empty(); + let can_go_forward = !frame.next.is_empty(); + let event = MozBrowserEvent::LocationChange(url, can_go_backward, can_go_forward); + parent_pipeline.trigger_mozbrowser_event(subpage_id, event); } } } } } + // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsererror + // Note that this does not require the pipeline to be an immediate child of the root + // TODO: propagate more error information, e.g. a backtrace + fn trigger_mozbrowsererror(&self, pipeline_id: PipelineId) { + if !prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) { return; } + + if let Some(pipeline) = self.pipelines.get(&pipeline_id) { + if let Some(mut ancestor_info) = pipeline.parent_info { + if let Some(mut ancestor) = self.pipelines.get(&ancestor_info.0) { + while let Some(next_info) = ancestor.parent_info { + ancestor_info = next_info; + ancestor = match self.pipelines.get(&ancestor_info.0) { + Some(ancestor) => ancestor, + None => return warn!("Mozbrowsererror via closed pipeline {:?}.", ancestor_info.0), + }; + } + let event = MozBrowserEvent::Error; + ancestor.trigger_mozbrowser_event(ancestor_info.1, event); + } + } + } + } + fn focused_pipeline_in_tree(&self, frame_id: FrameId) -> bool { self.focus_pipeline_id.map_or(false, |pipeline_id| { self.pipeline_exists_in_tree(pipeline_id, Some(frame_id)) @@ -1956,4 +1983,5 @@ impl Constellation self.current_frame_tree_iter(root_frame_id) .any(|current_frame| current_frame.current == pipeline_id) } + }