Skip to content

Commit

Permalink
Renamed ScriptChan in constellation to EventLoop.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Jeffrey committed Dec 15, 2016
1 parent 01b6ad5 commit e945e38
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 77 deletions.
91 changes: 34 additions & 57 deletions components/constellation/constellation.rs
Expand Up @@ -21,6 +21,7 @@ use debugger;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
use event_loop::EventLoop;
use gfx::font_cache_thread::FontCacheThread;
use gfx_traits::Epoch;
use ipc_channel::ipc::{self, IpcSender};
Expand Down Expand Up @@ -134,10 +135,10 @@ pub struct Constellation<Message, LTF, STF> {
/// to receive sw manager message
swmanager_receiver: Receiver<SWManagerMsg>,

/// A map from top-level frame id and registered domain name to script channels.
/// This double indirection ensures that separate tabs do not share script threads,
/// A map from top-level frame id and registered domain name to event loops.
/// This double indirection ensures that separate tabs do not share event loops,
/// even if the same domain is loaded in each.
script_channels: HashMap<FrameId, HashMap<String, Weak<ScriptChan>>>,
event_loops: HashMap<FrameId, HashMap<String, Weak<EventLoop>>>,

/// A list of all the pipelines. (See the `pipeline` module for more details.)
pipelines: HashMap<PipelineId, Pipeline>,
Expand Down Expand Up @@ -368,30 +369,6 @@ enum ExitPipelineMode {
Force,
}

/// A script channel, that closes the script thread down when it is dropped
pub struct ScriptChan {
chan: IpcSender<ConstellationControlMsg>,
dont_send_or_sync: PhantomData<Rc<()>>,
}

impl Drop for ScriptChan {
fn drop(&mut self) {
let _ = self.chan.send(ConstellationControlMsg::ExitScriptThread);
}
}

impl ScriptChan {
pub fn send(&self, msg: ConstellationControlMsg) -> Result<(), IOError> {
self.chan.send(msg)
}
pub fn new(chan: IpcSender<ConstellationControlMsg>) -> Rc<ScriptChan> {
Rc::new(ScriptChan { chan: chan, dont_send_or_sync: PhantomData })
}
pub fn sender(&self) -> IpcSender<ConstellationControlMsg> {
self.chan.clone()
}
}

/// A logger directed at the constellation from content processes
#[derive(Clone)]
pub struct FromScriptLogger {
Expand Down Expand Up @@ -533,7 +510,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
swmanager_chan: None,
swmanager_receiver: swmanager_receiver,
swmanager_sender: sw_mgr_clone,
script_channels: HashMap::new(),
event_loops: HashMap::new(),
pipelines: HashMap::new(),
frames: HashMap::new(),
pending_frames: vec!(),
Expand Down Expand Up @@ -608,17 +585,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => self.root_frame_id,
};

let (script_channel, host) = match sandbox {
let (event_loop, host) = match sandbox {
IFrameSandboxState::IFrameSandboxed => (None, None),
IFrameSandboxState::IFrameUnsandboxed => match reg_host(&load_data.url) {
None => (None, None),
Some(host) => {
let script_channel = self.script_channels.get(&top_level_frame_id)
let event_loop = self.event_loops.get(&top_level_frame_id)
.and_then(|map| map.get(host))
.and_then(|weak| weak.upgrade());
match script_channel {
match event_loop {
None => (None, Some(String::from(host))),
Some(script_channel) => (Some(script_channel.clone()), None),
Some(event_loop) => (Some(event_loop.clone()), None),
}
},
},
Expand Down Expand Up @@ -665,7 +642,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
time_profiler_chan: self.time_profiler_chan.clone(),
mem_profiler_chan: self.mem_profiler_chan.clone(),
window_size: initial_window_size,
script_chan: script_channel,
event_loop: event_loop,
load_data: load_data,
device_pixel_ratio: self.window_size.device_pixel_ratio,
pipeline_namespace_id: self.next_pipeline_namespace_id(),
Expand All @@ -680,9 +657,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};

if let Some(host) = host {
self.script_channels.entry(top_level_frame_id)
self.event_loops.entry(top_level_frame_id)
.or_insert_with(HashMap::new)
.insert(host, Rc::downgrade(&pipeline.script_chan));
.insert(host, Rc::downgrade(&pipeline.event_loop));
}

assert!(!self.pipelines.contains_key(&pipeline_id));
Expand Down Expand Up @@ -970,7 +947,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
let result = match self.pipelines.get(&pipeline_id) {
None => { debug!("Pipeline {:?} got event after closure.", pipeline_id); return; }
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
};
if let Err(e) = result {
self.handle_send_error(pipeline_id, e);
Expand Down Expand Up @@ -1118,7 +1095,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let msg = ConstellationControlMsg::DispatchStorageEvent(
pipeline.id, storage, url.clone(), key.clone(), old_value.clone(), new_value.clone()
);
if let Err(err) = pipeline.script_chan.send(msg) {
if let Err(err) = pipeline.event_loop.send(msg) {
warn!("Failed to broadcast storage event to pipeline {} ({:?}).", pipeline.id, err);
}
}
Expand Down Expand Up @@ -1327,7 +1304,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
match self.pipelines.get_mut(&pipeline_id) {
Some(pipeline) => {
pipeline.size = Some(*size);
pipeline.script_chan.send(msg)
pipeline.event_loop.send(msg)
}
None => return,
}
Expand All @@ -1352,7 +1329,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
child: pipeline_id,
};
let result = match self.pipelines.get(&parent_id) {
Some(parent) => parent.script_chan.send(msg),
Some(parent) => parent.event_loop.send(msg),
None => return warn!("Parent {} frame loaded after closure.", parent_id),
};
if let Err(e) = result {
Expand Down Expand Up @@ -1432,7 +1409,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id),
};

let script_sender = parent_pipeline.script_chan.clone();
let script_sender = parent_pipeline.event_loop.clone();

let url = ServoUrl::parse("about:blank").expect("infallible");
Pipeline::new(new_pipeline_id,
Expand Down Expand Up @@ -1475,7 +1452,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
AnimationTickType::Script => {
let msg = ConstellationControlMsg::TickAllAnimations(pipeline_id);
match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
None => return warn!("Pipeline {:?} got script tick after closure.", pipeline_id),
}
}
Expand Down Expand Up @@ -1548,7 +1525,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// and issue an iframe load through there.
let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, frame_id, load_data, replace);
let result = match self.pipelines.get(&parent_pipeline_id) {
Some(parent_pipeline) => parent_pipeline.script_chan.send(msg),
Some(parent_pipeline) => parent_pipeline.event_loop.send(msg),
None => {
warn!("Pipeline {:?} child loaded after closure", parent_pipeline_id);
return None;
Expand Down Expand Up @@ -1694,7 +1671,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let event = CompositorEvent::KeyEvent(ch, key, state, mods);
let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
let result = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
None => return debug!("Pipeline {:?} got key event after closure.", pipeline_id),
};
if let Err(e) = result {
Expand All @@ -1716,7 +1693,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if let Some(pipeline_id) = root_pipeline_id {
let msg = ConstellationControlMsg::Reload(pipeline_id);
let result = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
None => return debug!("Pipeline {:?} got reload event after closure.", pipeline_id),
};
if let Err(e) = result {
Expand All @@ -1728,7 +1705,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_get_pipeline_title_msg(&mut self, pipeline_id: PipelineId) {
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)),
Some(pipeline) => pipeline.event_loop.send(ConstellationControlMsg::GetTitle(pipeline_id)),
};
if let Err(e) = result {
self.handle_send_error(pipeline_id, e);
Expand Down Expand Up @@ -1791,7 +1768,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// telling it to mark the iframe element as focused.
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id);
let result = match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
};
if let Err(e) = result {
Expand Down Expand Up @@ -1853,7 +1830,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
visibility);
let result = match self.pipelines.get(&parent_pipeline_id) {
None => return warn!("Parent pipeline {:?} closed", parent_pipeline_id),
Some(parent_pipeline) => parent_pipeline.script_chan.send(visibility_msg),
Some(parent_pipeline) => parent_pipeline.event_loop.send(visibility_msg),
};

if let Err(e) = result {
Expand Down Expand Up @@ -1911,22 +1888,22 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd) => {
let control_msg = ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, cmd);
let result = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(control_msg),
Some(pipeline) => pipeline.event_loop.send(control_msg),
None => return warn!("Pipeline {:?} ScriptCommand after closure.", pipeline_id),
};
if let Err(e) = result {
self.handle_send_error(pipeline_id, e);
}
},
WebDriverCommandMsg::SendKeys(pipeline_id, cmd) => {
let script_channel = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.script_chan.clone(),
let event_loop = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.event_loop.clone(),
None => return warn!("Pipeline {:?} SendKeys after closure.", pipeline_id),
};
for (key, mods, state) in cmd {
let event = CompositorEvent::KeyEvent(None, key, state, mods);
let control_msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
if let Err(e) = script_channel.send(control_msg) {
if let Err(e) = event_loop.send(control_msg) {
return self.handle_send_error(pipeline_id, e);
}
}
Expand Down Expand Up @@ -2015,7 +1992,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
next_pipeline_id);
let result = match self.pipelines.get(&parent_pipeline_id) {
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
Some(pipeline) => pipeline.script_chan.send(msg),
Some(pipeline) => pipeline.event_loop.send(msg),
};
if let Err(e) = result {
self.handle_send_error(parent_pipeline_id, e);
Expand Down Expand Up @@ -2112,7 +2089,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
let msg = ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline.frame_id);
let _ = parent_pipeline.script_chan.send(msg);
let _ = parent_pipeline.event_loop.send(msg);
}
}
}
Expand Down Expand Up @@ -2143,7 +2120,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
Some(pipeline) => pipeline,
};
let _ = pipeline.script_chan.send(ConstellationControlMsg::Resize(
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
pipeline.id,
new_size,
size_type
Expand All @@ -2156,7 +2133,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
Some(pipeline) => pipeline,
};
let _ = pipeline.script_chan.send(ConstellationControlMsg::ResizeInactive(
let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive(
pipeline.id,
new_size
));
Expand All @@ -2171,7 +2148,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Some(pipeline) => pipeline,
};
if pipeline.parent_info.is_none() {
let _ = pipeline.script_chan.send(ConstellationControlMsg::Resize(
let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
pipeline.id,
new_size,
size_type
Expand Down Expand Up @@ -2340,7 +2317,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>

self.close_frame_children(frame_id, exit_mode);

self.script_channels.remove(&frame_id);
self.event_loops.remove(&frame_id);
if self.frames.remove(&frame_id).is_none() {
warn!("Closing frame {:?} twice.", frame_id);
}
Expand Down
46 changes: 46 additions & 0 deletions components/constellation/event_loop.rs
@@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! This module contains the `EventLoop` type, which is the constellation's
//! view of a script thread. When an `EventLoop` is dropped, an `ExitScriptThread`
//! message is sent to the script thread, asking it to shut down.

use ipc_channel::ipc::IpcSender;
use script_traits::ConstellationControlMsg;
use std::io::Error as IOError;
use std::marker::PhantomData;
use std::rc::Rc;

/// https://html.spec.whatwg.org/multipage/#event-loop
pub struct EventLoop {
script_chan: IpcSender<ConstellationControlMsg>,
dont_send_or_sync: PhantomData<Rc<()>>,
}

impl Drop for EventLoop {
fn drop(&mut self) {
let _ = self.script_chan.send(ConstellationControlMsg::ExitScriptThread);
}
}

impl EventLoop {
/// Create a new event loop from the channel to its script thread.
pub fn new(script_chan: IpcSender<ConstellationControlMsg>) -> Rc<EventLoop> {
Rc::new(EventLoop {
script_chan: script_chan,
dont_send_or_sync: PhantomData,
})
}

/// Send a message to the event loop.
pub fn send(&self, msg: ConstellationControlMsg) -> Result<(), IOError> {
self.script_chan.send(msg)
}

/// The underlying channel to the script thread.
pub fn sender(&self) -> IpcSender<ConstellationControlMsg> {
self.script_chan.clone()
}
}

1 change: 1 addition & 0 deletions components/constellation/lib.rs
Expand Up @@ -43,6 +43,7 @@ extern crate util;
extern crate webrender_traits;

mod constellation;
mod event_loop;
mod pipeline;
#[cfg(not(target_os = "windows"))]
mod sandboxing;
Expand Down

0 comments on commit e945e38

Please sign in to comment.