aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/constellation.rs133
1 files changed, 75 insertions, 58 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index 159477e34cb..6ebe4dd9c53 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -426,7 +426,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
//
// Yes, that's all there is to it!
if opts::multiprocess() {
- self.spawn_multiprocess(unprivileged_pipeline_content);
+ self.spawn_multiprocess(pipeline_id, unprivileged_pipeline_content);
} else {
unprivileged_pipeline_content.start_all::<LTF, STF>(false);
}
@@ -437,7 +437,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
#[cfg(not(target_os = "windows"))]
- fn spawn_multiprocess(&mut self, unprivileged_pipeline_content: UnprivilegedPipelineContent) {
+ fn spawn_multiprocess(&mut self,
+ pipeline_id: PipelineId,
+ unprivileged_pipeline_content: UnprivilegedPipelineContent)
+ {
let (server, token) =
IpcOneShotServer::<IpcSender<UnprivilegedPipelineContent>>::new().unwrap();
@@ -458,11 +461,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
self.child_processes.push(child_process);
let (_receiver, sender) = server.accept().unwrap();
- sender.send(unprivileged_pipeline_content).unwrap();
+ sender.send(unprivileged_pipeline_content)
+ .unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
#[cfg(target_os = "windows")]
- fn spawn_multiprocess(&mut self, _: UnprivilegedPipelineContent) {
+ fn spawn_multiprocess(&mut self, _: PipelineId, _: UnprivilegedPipelineContent) {
panic!("Multiprocess is not supported on Windows.");
}
@@ -670,16 +674,18 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
Request::Script(FromScriptMsg::ForwardMouseButtonEvent(
pipeline_id, event_type, button, point)) => {
- if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
- pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline_id,
- CompositorEvent::MouseButtonEvent(event_type, button, point))).unwrap();
- }
+ let event = CompositorEvent::MouseButtonEvent(event_type, button, point);
+ let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
+ self.pipelines.get(&pipeline_id)
+ .and_then(|pipeline| pipeline.script_chan.send(msg).ok())
+ .unwrap_or_else(|| self.handle_send_error(pipeline_id));
}
Request::Script(FromScriptMsg::ForwardMouseMoveEvent(pipeline_id, point)) => {
- if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
- pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline_id,
- CompositorEvent::MouseMoveEvent(Some(point)))).unwrap();
- }
+ let event = CompositorEvent::MouseMoveEvent(Some(point));
+ let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
+ self.pipelines.get(&pipeline_id)
+ .and_then(|pipeline| pipeline.script_chan.send(msg).ok())
+ .unwrap_or_else(|| self.handle_send_error(pipeline_id));
}
Request::Script(FromScriptMsg::GetClipboardContents(sender)) => {
let result = self.clipboard_ctx.as_ref().map_or(
@@ -689,7 +695,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
"".to_owned()
})
);
- sender.send(result).unwrap();
+ sender.send(result).unwrap_or_else(|e| debug!("Failed to send clipboard ({})", e))
}
Request::Script(FromScriptMsg::SetClipboardContents(s)) => {
if let Some(ref mut ctx) = self.clipboard_ctx {
@@ -767,16 +773,27 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
pipeline.exit();
}
self.image_cache_thread.exit();
- self.resource_thread.send(net_traits::ControlMsg::Exit).unwrap();
+ self.resource_thread.send(net_traits::ControlMsg::Exit)
+ .unwrap_or_else(|e| debug!("Exit resource thread failed ({})", e));
self.devtools_chan.as_ref().map(|chan| {
- chan.send(DevtoolsControlMsg::FromChrome(
- ChromeToDevtoolsControlMsg::ServerExitMsg)).unwrap();
+ chan.send(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg))
+ .unwrap_or_else(|e| debug!("Exit devtools failed ({})", e));
});
- self.storage_thread.send(StorageThreadMsg::Exit).unwrap();
+ self.storage_thread.send(StorageThreadMsg::Exit)
+ .unwrap_or_else(|e| debug!("Exit storage thread failed ({})", e));
self.font_cache_thread.exit();
self.compositor_proxy.send(ToCompositorMsg::ShutdownComplete);
}
+ fn handle_send_error(&mut self, pipeline_id: PipelineId) {
+ let parent_info = match self.pipelines.get(&pipeline_id) {
+ None => return debug!("Pipeline {:?} send error after closure.", pipeline_id),
+ Some(pipeline) => pipeline.parent_info,
+ };
+ // Treat send error the same as receiving a failure message
+ self.handle_failure_msg(pipeline_id, parent_info);
+ }
+
fn handle_failure_msg(&mut self,
pipeline_id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>) {
@@ -840,21 +857,20 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
visible_viewport: *size,
initial_viewport: *size * ScaleFactor::new(1.0),
device_pixel_ratio: self.window_size.device_pixel_ratio,
- })).unwrap();
+ })).unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) {
- let subframe_pipeline = self.pipeline(pipeline_id);
- let subframe_parent = match subframe_pipeline.parent_info {
- Some(ref parent) => parent,
+ let subframe_parent_id = match self.pipeline(pipeline_id).parent_info {
+ Some(ref parent) => parent.0,
None => return,
};
- let parent_pipeline = self.pipeline(subframe_parent.0);
let msg = ConstellationControlMsg::DispatchFrameLoadEvent {
target: pipeline_id,
- parent: subframe_parent.0,
+ parent: subframe_parent_id,
};
- parent_pipeline.script_chan.send(msg).unwrap();
+ self.pipeline(subframe_parent_id).script_chan.send(msg)
+ .unwrap_or_else(|_| self.handle_send_error(subframe_parent_id));
}
// The script thread associated with pipeline_id has loaded a URL in an iframe via script. This
@@ -934,14 +950,14 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
self.pipeline(pipeline_id)
.script_chan
.send(ConstellationControlMsg::TickAllAnimations(pipeline_id))
- .unwrap();
+ .unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
AnimationTickType::Layout => {
self.pipeline(pipeline_id)
.layout_chan
.0
.send(LayoutControlMsg::TickAnimations)
- .unwrap();
+ .unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
}
}
@@ -960,11 +976,9 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
self.handle_load_start_msg(&source_id);
// Message the constellation to find the script thread for this iframe
// and issue an iframe load through there.
- let parent_pipeline = self.pipeline(parent_pipeline_id);
- let script_channel = &parent_pipeline.script_chan;
- script_channel.send(ConstellationControlMsg::Navigate(parent_pipeline_id,
- subpage_id,
- load_data)).unwrap();
+ let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, subpage_id, load_data);
+ self.pipeline(parent_pipeline_id).script_chan.send(msg)
+ .unwrap_or_else(|_| self.handle_send_error(parent_pipeline_id));
Some(source_id)
}
None => {
@@ -1110,11 +1124,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
// Update the owning iframe to point to the new subpage id.
// This makes things like contentDocument work correctly.
if let Some((parent_pipeline_id, subpage_id)) = pipeline_info {
- let script_chan = &self.pipeline(parent_pipeline_id).script_chan;
let (_, new_subpage_id) = self.pipeline(next_pipeline_id).parent_info.unwrap();
- script_chan.send(ConstellationControlMsg::UpdateSubpageId(parent_pipeline_id,
- subpage_id,
- new_subpage_id)).unwrap();
+ let msg = ConstellationControlMsg::UpdateSubpageId(parent_pipeline_id, subpage_id, new_subpage_id);
+ self.pipeline(parent_pipeline_id).script_chan.send(msg)
+ .unwrap_or_else(|_| self.handle_send_error(parent_pipeline_id));
// If this is an iframe, send a mozbrowser location change event.
// This is the result of a back/forward navigation.
@@ -1122,7 +1135,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
}
- fn handle_key_msg(&self, key: Key, state: KeyState, mods: KeyModifiers) {
+ fn handle_key_msg(&mut self, key: Key, state: KeyState, mods: KeyModifiers) {
// Send to the explicitly focused pipeline (if it exists), or the root
// frame's current pipeline. If neither exist, fall back to sending to
// the compositor below.
@@ -1132,10 +1145,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
match target_pipeline_id {
Some(target_pipeline_id) => {
- let pipeline = self.pipeline(target_pipeline_id);
let event = CompositorEvent::KeyEvent(key, state, mods);
- pipeline.script_chan.send(
- ConstellationControlMsg::SendEvent(pipeline.id, event)).unwrap();
+ let msg = ConstellationControlMsg::SendEvent(target_pipeline_id, event);
+ self.pipeline(target_pipeline_id).script_chan.send(msg)
+ .unwrap_or_else(|_| self.handle_send_error(target_pipeline_id));
}
None => {
let event = ToCompositorMsg::KeyEvent(key, state, mods);
@@ -1145,12 +1158,11 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
}
fn handle_get_pipeline_title_msg(&mut self, pipeline_id: PipelineId) {
- match self.pipelines.get(&pipeline_id) {
- None => self.compositor_proxy.send(ToCompositorMsg::ChangePageTitle(pipeline_id, None)),
- Some(pipeline) => {
- pipeline.script_chan.send(ConstellationControlMsg::GetTitle(pipeline_id)).unwrap();
- }
- }
+ let result = match self.pipelines.get(&pipeline_id) {
+ None => return self.compositor_proxy.send(ToCompositorMsg::ChangePageTitle(pipeline_id, None)),
+ Some(pipeline) => pipeline.script_chan.send(ConstellationControlMsg::GetTitle(pipeline_id)),
+ };
+ result.unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
fn handle_mozbrowser_event_msg(&mut self,
@@ -1172,24 +1184,26 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
let pipeline_id = self.pending_frames.iter().rev()
.find(|x| x.old_pipeline_id == current_pipeline_id)
.map(|x| x.new_pipeline_id).or(current_pipeline_id);
- resp_chan.send(pipeline_id).unwrap();
+ resp_chan.send(pipeline_id)
+ .unwrap_or_else(|_| debug!("Failed get_pipeline response."));
}
fn handle_get_frame(&mut self,
pipeline_id: PipelineId,
resp_chan: IpcSender<Option<FrameId>>) {
let frame_id = self.pipeline_to_frame_map.get(&pipeline_id).map(|x| *x);
- resp_chan.send(frame_id).unwrap();
+ resp_chan.send(frame_id)
+ .unwrap_or_else(|_| debug!("Failed get_pipeline response."));
}
- fn focus_parent_pipeline(&self, pipeline_id: PipelineId) {
+ fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) {
// Send a message to the parent of the provided pipeline (if it exists)
// telling it to mark the iframe element as focused.
if let Some((containing_pipeline_id, subpage_id)) = self.pipeline(pipeline_id).parent_info {
- let pipeline = self.pipeline(containing_pipeline_id);
let event = ConstellationControlMsg::FocusIFrame(containing_pipeline_id,
subpage_id);
- pipeline.script_chan.send(event).unwrap();
+ self.pipeline(containing_pipeline_id).script_chan.send(event)
+ .unwrap_or_else(|_| self.handle_send_error(containing_pipeline_id));
self.focus_parent_pipeline(containing_pipeline_id);
}
@@ -1224,7 +1238,8 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
response_sender: IpcSender<IpcSender<CanvasMsg>>) {
let webrender_api = self.webrender_api_sender.clone();
let sender = CanvasPaintThread::start(*size, webrender_api);
- response_sender.send(sender).unwrap()
+ response_sender.send(sender)
+ .unwrap_or_else(|e| debug!("Create canvas paint thread response failed ({})", e))
}
fn handle_create_webgl_paint_thread_msg(
@@ -1235,7 +1250,8 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
let webrender_api = self.webrender_api_sender.clone();
let sender = WebGLPaintThread::start(*size, attributes, webrender_api);
- response_sender.send(sender).unwrap()
+ response_sender.send(sender)
+ .unwrap_or_else(|e| debug!("Create WebGL paint thread response failed ({})", e))
}
fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) {
@@ -1253,16 +1269,16 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
self.load_url_for_webdriver(pipeline_id, load_data, reply);
}
WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd) => {
- let pipeline = self.pipeline(pipeline_id);
let control_msg = ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, cmd);
- pipeline.script_chan.send(control_msg).unwrap();
+ self.pipeline(pipeline_id).script_chan.send(control_msg)
+ .unwrap_or_else(|_| self.handle_send_error(pipeline_id));
},
WebDriverCommandMsg::SendKeys(pipeline_id, cmd) => {
- let pipeline = self.pipeline(pipeline_id);
for (key, mods, state) in cmd {
let event = CompositorEvent::KeyEvent(key, state, mods);
- pipeline.script_chan.send(
- ConstellationControlMsg::SendEvent(pipeline.id, event)).unwrap();
+ let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
+ self.pipeline(pipeline_id).script_chan.send(msg)
+ .unwrap_or_else(|_| self.handle_send_error(pipeline_id));
}
},
WebDriverCommandMsg::TakeScreenshot(pipeline_id, reply) => {
@@ -1271,7 +1287,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
if Some(pipeline_id) == current_pipeline_id {
self.compositor_proxy.send(ToCompositorMsg::CreatePng(reply));
} else {
- reply.send(None).unwrap();
+ reply.send(None).unwrap_or_else(|e| debug!("Screenshot reply failed ({})", e));
}
},
}
@@ -1439,6 +1455,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
/// and compares the current layout state to what the compositor has. This is used
/// to check if the output image is "stable" and can be written as a screenshot
/// for reftests.
+ /// Since this function is only used in reftests, we do not harden it against panic.
fn handle_is_ready_to_save_image(&mut self,
pipeline_states: HashMap<PipelineId, Epoch>) -> ReadyToSave {
// If there is no root frame yet, the initial page has