Auto merge of #8599 - jdm:e10s-redux, r=metajack

compositing: Split Servo up into multiple sandboxed processes.

Multiprocess mode is enabled with the `-M` switch, and sandboxing is
enabled with the `-S` switch.

Rebase of #6884.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8599)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-11-20 03:59:48 +05:30
commit 8b39b9afed
33 changed files with 688 additions and 265 deletions

View file

@ -68,14 +68,20 @@ features = ["texture_surface"]
version = "0.2" version = "0.2"
features = [ "serde_serialization" ] features = [ "serde_serialization" ]
[dependencies.gaol]
git = "https://github.com/pcwalton/gaol"
[dependencies] [dependencies]
app_units = {version = "0.1", features = ["plugins"]} app_units = {version = "0.1", features = ["plugins"]}
image = "0.4.0" image = "0.4.0"
libc = "0.1"
log = "0.3" log = "0.3"
num = "0.1.24" num = "0.1.24"
time = "0.1.17" time = "0.1.17"
gleam = "0.1" gleam = "0.1"
euclid = {version = "0.3", features = ["plugins"]} euclid = {version = "0.3", features = ["plugins"]}
serde = "0.6"
serde_macros = "0.6"
[target.x86_64-apple-darwin.dependencies] [target.x86_64-apple-darwin.dependencies]
core-graphics = "0.1" core-graphics = "0.1"

View file

@ -17,7 +17,7 @@ use gfx_traits::color;
use gleam::gl; use gleam::gl;
use gleam::gl::types::{GLint, GLsizei}; use gleam::gl::types::{GLint, GLsizei};
use image::{DynamicImage, ImageFormat, RgbImage}; use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory}; use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use layers::geometry::{DevicePixel, LayerPixel}; use layers::geometry::{DevicePixel, LayerPixel};
use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet};
@ -30,7 +30,7 @@ use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerKind};
use msg::compositor_msg::{LayerProperties, ScrollPolicy}; use msg::compositor_msg::{LayerProperties, ScrollPolicy};
use msg::constellation_msg::CompositorMsg as ConstellationMsg; use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::{AnimationState, Image, PixelFormat}; use msg::constellation_msg::{AnimationState, Image, PixelFormat};
use msg::constellation_msg::{ConstellationChan, Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData}; use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
use pipeline::CompositionPipeline; use pipeline::CompositionPipeline;
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest}; use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
@ -168,7 +168,7 @@ pub struct IOCompositor<Window: WindowMethods> {
frame_tree_id: FrameTreeId, frame_tree_id: FrameTreeId,
/// The channel on which messages can be sent to the constellation. /// The channel on which messages can be sent to the constellation.
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: Sender<ConstellationMsg>,
/// The channel on which messages can be sent to the time profiler. /// The channel on which messages can be sent to the time profiler.
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
@ -385,8 +385,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
pub fn start_shutting_down(&mut self) { pub fn start_shutting_down(&mut self) {
debug!("Compositor sending Exit message to Constellation"); debug!("Compositor sending Exit message to Constellation");
let ConstellationChan(ref constellation_channel) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::Exit).unwrap();
constellation_channel.send(ConstellationMsg::Exit).unwrap();
self.mem_profiler_chan.send(mem::ProfilerMsg::UnregisterReporter(reporter_name())); self.mem_profiler_chan.send(mem::ProfilerMsg::UnregisterReporter(reporter_name()));
@ -702,8 +701,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn set_frame_tree(&mut self, fn set_frame_tree(&mut self,
frame_tree: &SendableFrameTree, frame_tree: &SendableFrameTree,
response_chan: Sender<()>, response_chan: IpcSender<()>,
new_constellation_chan: ConstellationChan<ConstellationMsg>) { new_constellation_chan: Sender<ConstellationMsg>) {
response_chan.send(()).unwrap(); response_chan.send(()).unwrap();
// There are now no more pending iframes. // There are now no more pending iframes.
@ -943,8 +942,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let initial_viewport = self.window_size.as_f32() / dppx; let initial_viewport = self.window_size.as_f32() / dppx;
let visible_viewport = initial_viewport / self.viewport_zoom; let visible_viewport = initial_viewport / self.viewport_zoom;
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
device_pixel_ratio: dppx, device_pixel_ratio: dppx,
initial_viewport: initial_viewport, initial_viewport: initial_viewport,
visible_viewport: visible_viewport, visible_viewport: visible_viewport,
@ -959,9 +957,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
None => return, None => return,
}; };
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::FrameSize(
chan.send(ConstellationMsg::FrameSize(*subpage_pipeline_id, *subpage_pipeline_id,
layer_properties.rect.size)).unwrap(); layer_properties.rect.size)).unwrap();
} }
pub fn move_layer(&self, pub fn move_layer(&self,
@ -1168,8 +1166,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
None => ConstellationMsg::InitLoadUrl(url) None => ConstellationMsg::InitLoadUrl(url)
}; };
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(msg).unwrap()
chan.send(msg).unwrap()
} }
fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) { fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) {
@ -1446,7 +1443,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
} }
fn tick_animations_for_pipeline(&self, pipeline_id: PipelineId) { fn tick_animations_for_pipeline(&self, pipeline_id: PipelineId) {
self.constellation_chan.0.send(ConstellationMsg::TickAnimation(pipeline_id)).unwrap() self.constellation_chan.send(ConstellationMsg::TickAnimation(pipeline_id)).unwrap()
} }
fn constrain_viewport(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) { fn constrain_viewport(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) {
@ -1538,13 +1535,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
windowing::WindowNavigateMsg::Forward => NavigationDirection::Forward, windowing::WindowNavigateMsg::Forward => NavigationDirection::Forward,
windowing::WindowNavigateMsg::Back => NavigationDirection::Back, windowing::WindowNavigateMsg::Back => NavigationDirection::Back,
}; };
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::Navigate(None, direction)).unwrap()
chan.send(ConstellationMsg::Navigate(None, direction)).unwrap()
} }
fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) { fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) {
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
} }
fn fill_paint_request_with_cached_layer_buffers(&mut self, paint_request: &mut PaintRequest) { fn fill_paint_request_with_cached_layer_buffers(&mut self, paint_request: &mut PaintRequest) {
@ -1744,8 +1739,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// Pass the pipeline/epoch states to the constellation and check // Pass the pipeline/epoch states to the constellation and check
// if it's safe to output the image. // if it's safe to output the image.
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::IsReadyToSaveImage(pipeline_epochs)).unwrap();
chan.send(ConstellationMsg::IsReadyToSaveImage(pipeline_epochs)).unwrap();
self.ready_to_save_state = ReadyState::WaitingForConstellationReply; self.ready_to_save_state = ReadyState::WaitingForConstellationReply;
Err(NotReadyToPaint::JustNotifiedConstellation) Err(NotReadyToPaint::JustNotifiedConstellation)
} }
@ -2167,8 +2161,7 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind
None => return, None => return,
Some(ref root_pipeline) => root_pipeline.id, Some(ref root_pipeline) => root_pipeline.id,
}; };
let ConstellationChan(ref chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id)).unwrap();
chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id)).unwrap();
} }
} }

View file

@ -5,15 +5,16 @@
//! Communication with the compositor task. //! Communication with the compositor task.
use compositor; use compositor;
use euclid::{Point2D, Size2D}; use euclid::point::Point2D;
use euclid::size::Size2D;
use headless; use headless;
use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use layers::layers::{BufferRequest, LayerBufferSet}; use layers::layers::{BufferRequest, LayerBufferSet};
use layers::platform::surface::{NativeDisplay, NativeSurface}; use layers::platform::surface::{NativeDisplay, NativeSurface};
use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerProperties}; use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerProperties};
use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg}; use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
use msg::constellation_msg::CompositorMsg as ConstellationMsg; use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId}; use msg::constellation_msg::{AnimationState, PipelineId};
use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState}; use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState};
use profile_traits::mem; use profile_traits::mem;
use profile_traits::time; use profile_traits::time;
@ -60,11 +61,11 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
receiver: IpcReceiver<ScriptToCompositorMsg>) { receiver: IpcReceiver<ScriptToCompositorMsg>) {
while let Ok(msg) = receiver.recv() { while let Ok(msg) = receiver.recv() {
match msg { match msg {
ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point, _smooth) => { ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point, smooth) => {
compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id,
layer_id, layer_id,
point, point,
_smooth)); smooth));
} }
ScriptToCompositorMsg::GetClientWindow(send) => { ScriptToCompositorMsg::GetClientWindow(send) => {
@ -80,7 +81,7 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
} }
ScriptToCompositorMsg::Exit => { ScriptToCompositorMsg::Exit => {
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
compositor_proxy.send(Msg::Exit(chan)); compositor_proxy.send(Msg::Exit(chan));
port.recv().unwrap(); port.recv().unwrap();
} }
@ -152,7 +153,7 @@ impl PaintListener for Box<CompositorProxy + 'static + Send> {
/// Messages from the painting task and the constellation task to the compositor task. /// Messages from the painting task and the constellation task to the compositor task.
pub enum Msg { pub enum Msg {
/// Requests that the compositor shut down. /// Requests that the compositor shut down.
Exit(Sender<()>), Exit(IpcSender<()>),
/// Informs the compositor that the constellation has completed shutdown. /// Informs the compositor that the constellation has completed shutdown.
/// Required because the constellation can have pending calls to make /// Required because the constellation can have pending calls to make
@ -180,7 +181,7 @@ pub enum Msg {
/// Alerts the compositor that the given pipeline has changed whether it is running animations. /// Alerts the compositor that the given pipeline has changed whether it is running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState), ChangeRunningAnimationsState(PipelineId, AnimationState),
/// Replaces the current frame tree, typically called during main frame navigation. /// Replaces the current frame tree, typically called during main frame navigation.
SetFrameTree(SendableFrameTree, Sender<()>, ConstellationChan<ConstellationMsg>), SetFrameTree(SendableFrameTree, IpcSender<()>, Sender<ConstellationMsg>),
/// The load of a page has begun: (can go back, can go forward). /// The load of a page has begun: (can go back, can go forward).
LoadStart(bool, bool), LoadStart(bool, bool),
/// The load of a page has completed: (can go back, can go forward). /// The load of a page has completed: (can go back, can go forward).
@ -296,7 +297,7 @@ pub struct InitialCompositorState {
/// A port on which messages inbound to the compositor can be received. /// A port on which messages inbound to the compositor can be received.
pub receiver: Box<CompositorReceiver>, pub receiver: Box<CompositorReceiver>,
/// A channel to the constellation. /// A channel to the constellation.
pub constellation_chan: ConstellationChan<ConstellationMsg>, pub constellation_chan: Sender<ConstellationMsg>,
/// A channel to the time profiler thread. /// A channel to the time profiler thread.
pub time_profiler_chan: time::ProfilerChan, pub time_profiler_chan: time::ProfilerChan,
/// A channel to the memory profiler thread. /// A channel to the memory profiler thread.

View file

@ -18,8 +18,11 @@ use compositor_task::Msg as ToCompositorMsg;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
use euclid::scale_factor::ScaleFactor; use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D}; use euclid::size::{Size2D, TypedSize2D};
use gaol;
use gaol::sandbox::{self, Sandbox, SandboxMethods};
use gfx::font_cache_task::FontCacheTask; use gfx::font_cache_task::FontCacheTask;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcOneShotServer, IpcSender};
use ipc_channel::router::ROUTER;
use layout_traits::{LayoutControlChan, LayoutTaskFactory}; use layout_traits::{LayoutControlChan, LayoutTaskFactory};
use msg::compositor_msg::Epoch; use msg::compositor_msg::Epoch;
use msg::constellation_msg::AnimationState; use msg::constellation_msg::AnimationState;
@ -37,19 +40,21 @@ use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::{StorageTask, StorageTaskMsg}; use net_traits::storage_task::{StorageTask, StorageTaskMsg};
use net_traits::{self, ResourceTask}; use net_traits::{self, ResourceTask};
use offscreen_gl_context::GLContextAttributes; use offscreen_gl_context::GLContextAttributes;
use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline}; use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline, UnprivilegedPipelineContent};
use profile_traits::mem; use profile_traits::mem;
use profile_traits::time; use profile_traits::time;
use sandboxing;
use script_traits::{CompositorEvent, ConstellationControlMsg, LayoutControlMsg}; use script_traits::{CompositorEvent, ConstellationControlMsg, LayoutControlMsg};
use script_traits::{ScriptState, ScriptTaskFactory}; use script_traits::{ScriptState, ScriptTaskFactory};
use script_traits::{TimerEventRequest}; use script_traits::{TimerEventRequest};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::collections::HashMap; use std::collections::HashMap;
use std::env;
use std::io::{self, Write}; use std::io::{self, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::replace; use std::mem::replace;
use std::process; use std::process;
use std::sync::mpsc::{Receiver, Sender, channel}; use std::sync::mpsc::{Sender, channel, Receiver};
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use timer_scheduler::TimerScheduler; use timer_scheduler::TimerScheduler;
use url::Url; use url::Url;
@ -79,7 +84,7 @@ pub struct Constellation<LTF, STF> {
pub script_sender: ConstellationChan<FromScriptMsg>, pub script_sender: ConstellationChan<FromScriptMsg>,
/// A channel through which compositor messages can be sent to this object. /// A channel through which compositor messages can be sent to this object.
pub compositor_sender: ConstellationChan<FromCompositorMsg>, pub compositor_sender: Sender<FromCompositorMsg>,
/// Receives messages from scripts. /// Receives messages from scripts.
pub script_receiver: Receiver<FromScriptMsg>, pub script_receiver: Receiver<FromScriptMsg>,
@ -156,6 +161,9 @@ pub struct Constellation<LTF, STF> {
webgl_paint_tasks: Vec<Sender<CanvasMsg>>, webgl_paint_tasks: Vec<Sender<CanvasMsg>>,
scheduler_chan: IpcSender<TimerEventRequest>, scheduler_chan: IpcSender<TimerEventRequest>,
/// A list of child content processes.
child_processes: Vec<ChildProcess>,
} }
/// State needed to construct a constellation. /// State needed to construct a constellation.
@ -259,14 +267,21 @@ enum ExitPipelineMode {
Force, Force,
} }
enum ChildProcess {
Sandboxed(gaol::platform::process::Process),
Unsandboxed(process::Child),
}
impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pub fn start(state: InitialConstellationState) -> ConstellationChan<FromCompositorMsg> { pub fn start(state: InitialConstellationState) -> Sender<FromCompositorMsg> {
let (script_receiver, script_sender) = ConstellationChan::<FromScriptMsg>::new(); let (ipc_script_receiver, ipc_script_sender) = ConstellationChan::<FromScriptMsg>::new();
let (compositor_receiver, compositor_sender) = ConstellationChan::<FromCompositorMsg>::new(); //let (script_receiver, script_sender) = channel();
let script_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_script_receiver);
let (compositor_sender, compositor_receiver) = channel();
let compositor_sender_clone = compositor_sender.clone(); let compositor_sender_clone = compositor_sender.clone();
spawn_named("Constellation".to_owned(), move || { spawn_named("Constellation".to_owned(), move || {
let mut constellation: Constellation<LTF, STF> = Constellation { let mut constellation: Constellation<LTF, STF> = Constellation {
script_sender: script_sender, script_sender: ipc_script_sender,
compositor_sender: compositor_sender_clone, compositor_sender: compositor_sender_clone,
script_receiver: script_receiver, script_receiver: script_receiver,
compositor_receiver: compositor_receiver, compositor_receiver: compositor_receiver,
@ -305,6 +320,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
canvas_paint_tasks: Vec::new(), canvas_paint_tasks: Vec::new(),
webgl_paint_tasks: Vec::new(), webgl_paint_tasks: Vec::new(),
scheduler_chan: TimerScheduler::start(), scheduler_chan: TimerScheduler::start(),
child_processes: Vec::new(),
}; };
let namespace_id = constellation.next_pipeline_namespace_id(); let namespace_id = constellation.next_pipeline_namespace_id();
PipelineNamespace::install(namespace_id); PipelineNamespace::install(namespace_id);
@ -333,10 +349,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pipeline_id: PipelineId, pipeline_id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>, parent_info: Option<(PipelineId, SubpageId)>,
initial_window_size: Option<TypedSize2D<PagePx, f32>>, initial_window_size: Option<TypedSize2D<PagePx, f32>>,
script_channel: Option<Sender<ConstellationControlMsg>>, script_channel: Option<IpcSender<ConstellationControlMsg>>,
load_data: LoadData) { load_data: LoadData) {
let spawning_paint_only = script_channel.is_some(); let spawning_paint_only = script_channel.is_some();
let (pipeline, mut pipeline_content) = let (pipeline, unprivileged_pipeline_content, mut privileged_pipeline_content) =
Pipeline::create::<LTF, STF>(InitialPipelineState { Pipeline::create::<LTF, STF>(InitialPipelineState {
id: pipeline_id, id: pipeline_id,
parent_info: parent_info, parent_info: parent_info,
@ -357,12 +373,39 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pipeline_namespace_id: self.next_pipeline_namespace_id(), pipeline_namespace_id: self.next_pipeline_namespace_id(),
}); });
// TODO(pcwalton): In multiprocess mode, send that `PipelineContent` instance over to
// the content process and call this over there.
if spawning_paint_only { if spawning_paint_only {
pipeline_content.start_paint_task(); privileged_pipeline_content.start_paint_task();
} else { } else {
pipeline_content.start_all::<LTF, STF>(); privileged_pipeline_content.start_all();
// Spawn the child process.
//
// Yes, that's all there is to it!
if opts::multiprocess() {
let (server, token) =
IpcOneShotServer::<IpcSender<UnprivilegedPipelineContent>>::new().unwrap();
// If there is a sandbox, use the `gaol` API to create the child process.
let child_process = if opts::get().sandbox {
let mut command = sandbox::Command::me().unwrap();
command.arg("--content-process").arg(token);
let profile = sandboxing::content_process_sandbox_profile();
ChildProcess::Sandboxed(Sandbox::new(profile).start(&mut command).expect(
"Failed to start sandboxed child process!"))
} else {
let path_to_self = env::current_exe().unwrap();
let mut child_process = process::Command::new(path_to_self);
child_process.arg("--content-process");
child_process.arg(token);
ChildProcess::Unsandboxed(child_process.spawn().unwrap())
};
self.child_processes.push(child_process);
let (_receiver, sender) = server.accept().unwrap();
sender.send(unprivileged_pipeline_content).unwrap();
} else {
unprivileged_pipeline_content.start_all::<LTF, STF>(false);
}
} }
assert!(!self.pipelines.contains_key(&pipeline_id)); assert!(!self.pipelines.contains_key(&pipeline_id));
@ -1290,7 +1333,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
// Synchronously query the script task for this pipeline // Synchronously query the script task for this pipeline
// to see if it is idle. // to see if it is idle.
let (sender, receiver) = channel(); let (sender, receiver) = ipc::channel().unwrap();
let msg = ConstellationControlMsg::GetCurrentState(sender, frame.current); let msg = ConstellationControlMsg::GetCurrentState(sender, frame.current);
pipeline.script_chan.send(msg).unwrap(); pipeline.script_chan.send(msg).unwrap();
let result = receiver.recv().unwrap(); let result = receiver.recv().unwrap();
@ -1445,7 +1488,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
if let Some(root_frame_id) = self.root_frame_id { if let Some(root_frame_id) = self.root_frame_id {
let frame_tree = self.frame_to_sendable(root_frame_id); let frame_tree = self.frame_to_sendable(root_frame_id);
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree, self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree,
chan, chan,
self.compositor_sender.clone())); self.compositor_sender.clone()));

View file

@ -8,9 +8,10 @@ use euclid::scale_factor::ScaleFactor;
use euclid::{Point2D, Size2D}; use euclid::{Point2D, Size2D};
use msg::constellation_msg::AnimationState; use msg::constellation_msg::AnimationState;
use msg::constellation_msg::CompositorMsg as ConstellationMsg; use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, WindowSizeData}; use msg::constellation_msg::WindowSizeData;
use profile_traits::mem; use profile_traits::mem;
use profile_traits::time; use profile_traits::time;
use std::sync::mpsc::Sender;
use util::opts; use util::opts;
use windowing::WindowEvent; use windowing::WindowEvent;
@ -22,7 +23,7 @@ pub struct NullCompositor {
/// The port on which we receive messages. /// The port on which we receive messages.
pub port: Box<CompositorReceiver>, pub port: Box<CompositorReceiver>,
/// A channel to the constellation. /// A channel to the constellation.
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: Sender<ConstellationMsg>,
/// A channel to the time profiler. /// A channel to the time profiler.
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
/// A channel to the memory profiler. /// A channel to the memory profiler.
@ -44,8 +45,7 @@ impl NullCompositor {
// Tell the constellation about the initial fake size. // Tell the constellation about the initial fake size.
{ {
let ConstellationChan(ref chan) = compositor.constellation_chan; compositor.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
initial_viewport: Size2D::typed(800_f32, 600_f32), initial_viewport: Size2D::typed(800_f32, 600_f32),
visible_viewport: Size2D::typed(800_f32, 600_f32), visible_viewport: Size2D::typed(800_f32, 600_f32),
device_pixel_ratio: device_pixel_ratio:
@ -62,8 +62,7 @@ impl CompositorEventListener for NullCompositor {
match self.port.recv_compositor_msg() { match self.port.recv_compositor_msg() {
Msg::Exit(chan) => { Msg::Exit(chan) => {
debug!("shutting down the constellation"); debug!("shutting down the constellation");
let ConstellationChan(ref con_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::Exit).unwrap();
con_chan.send(ConstellationMsg::Exit).unwrap();
chan.send(()).unwrap(); chan.send(()).unwrap();
} }
@ -100,7 +99,7 @@ impl CompositorEventListener for NullCompositor {
AnimationState::NoAnimationCallbacksPresent => {} AnimationState::NoAnimationCallbacksPresent => {}
AnimationState::AnimationCallbacksPresent => { AnimationState::AnimationCallbacksPresent => {
let msg = ConstellationMsg::TickAnimation(pipeline_id); let msg = ConstellationMsg::TickAnimation(pipeline_id);
self.constellation_chan.0.send(msg).unwrap() self.constellation_chan.send(msg).unwrap()
} }
} }
} }

View file

@ -3,7 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(custom_derive)]
#![feature(iter_cmp)] #![feature(iter_cmp)]
#![feature(plugin)]
#![feature(slice_bytes)] #![feature(slice_bytes)]
#![feature(vec_push_all)] #![feature(vec_push_all)]
#![feature(mpsc_select)] #![feature(mpsc_select)]
@ -11,6 +13,7 @@
#![plugin(plugins)] #![plugin(plugins)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![plugin(serde_macros)]
extern crate app_units; extern crate app_units;
#[macro_use] #[macro_use]
@ -31,6 +34,7 @@ extern crate core_text;
extern crate devtools_traits; extern crate devtools_traits;
extern crate euclid; extern crate euclid;
extern crate gaol;
extern crate gfx; extern crate gfx;
extern crate gfx_traits; extern crate gfx_traits;
extern crate gleam; extern crate gleam;
@ -43,7 +47,10 @@ extern crate net_traits;
extern crate num; extern crate num;
extern crate offscreen_gl_context; extern crate offscreen_gl_context;
extern crate script_traits; extern crate script_traits;
extern crate serde;
extern crate style_traits; extern crate style_traits;
extern crate libc;
extern crate time; extern crate time;
extern crate url; extern crate url;
@ -59,4 +66,5 @@ mod timer_scheduler;
pub mod compositor_task; pub mod compositor_task;
pub mod constellation; pub mod constellation;
pub mod pipeline; pub mod pipeline;
pub mod sandboxing;
pub mod windowing; pub mod windowing;

View file

@ -14,6 +14,7 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use layers::geometry::DevicePixel; use layers::geometry::DevicePixel;
use layout_traits::{LayoutControlChan, LayoutTaskFactory}; use layout_traits::{LayoutControlChan, LayoutTaskFactory};
use msg::compositor_msg::ScriptToCompositorMsg;
use msg::constellation_msg::ScriptMsg as ConstellationMsg; use msg::constellation_msg::ScriptMsg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId};
use msg::constellation_msg::{LoadData, MozBrowserEvent, WindowSizeData}; use msg::constellation_msg::{LoadData, MozBrowserEvent, WindowSizeData};
@ -26,7 +27,6 @@ use profile_traits::time;
use script_traits::{ConstellationControlMsg, InitialScriptState}; use script_traits::{ConstellationControlMsg, InitialScriptState};
use script_traits::{LayoutControlMsg, NewLayoutInfo, ScriptTaskFactory}; use script_traits::{LayoutControlMsg, NewLayoutInfo, ScriptTaskFactory};
use script_traits::{TimerEventRequest}; use script_traits::{TimerEventRequest};
use std::any::Any;
use std::mem; use std::mem;
use std::sync::mpsc::{Receiver, Sender, channel}; use std::sync::mpsc::{Receiver, Sender, channel};
use std::thread; use std::thread;
@ -34,20 +34,21 @@ use url::Url;
use util; use util;
use util::geometry::{PagePx, ViewportPx}; use util::geometry::{PagePx, ViewportPx};
use util::ipc::OptionalIpcSender; use util::ipc::OptionalIpcSender;
use util::opts::{self, Opts};
use util::prefs; use util::prefs;
/// A uniquely-identifiable pipeline of script task, layout task, and paint task. /// A uniquely-identifiable pipeline of script task, layout task, and paint task.
pub struct Pipeline { pub struct Pipeline {
pub id: PipelineId, pub id: PipelineId,
pub parent_info: Option<(PipelineId, SubpageId)>, pub parent_info: Option<(PipelineId, SubpageId)>,
pub script_chan: Sender<ConstellationControlMsg>, pub script_chan: IpcSender<ConstellationControlMsg>,
/// A channel to layout, for performing reflows and shutdown. /// A channel to layout, for performing reflows and shutdown.
pub layout_chan: LayoutControlChan, pub layout_chan: LayoutControlChan,
/// A channel to the compositor. /// A channel to the compositor.
pub compositor_proxy: Box<CompositorProxy + 'static + Send>, pub compositor_proxy: Box<CompositorProxy + 'static + Send>,
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>, pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
pub layout_shutdown_port: Receiver<()>, pub layout_shutdown_port: IpcReceiver<()>,
pub paint_shutdown_port: Receiver<()>, pub paint_shutdown_port: IpcReceiver<()>,
/// URL corresponding to the most recently-loaded page. /// URL corresponding to the most recently-loaded page.
pub url: Url, pub url: Url,
/// The title of the most recently-loaded page. /// The title of the most recently-loaded page.
@ -63,7 +64,7 @@ pub struct Pipeline {
#[derive(Clone)] #[derive(Clone)]
pub struct CompositionPipeline { pub struct CompositionPipeline {
pub id: PipelineId, pub id: PipelineId,
pub script_chan: Sender<ConstellationControlMsg>, pub script_chan: IpcSender<ConstellationControlMsg>,
pub layout_chan: LayoutControlChan, pub layout_chan: LayoutControlChan,
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>, pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
} }
@ -104,7 +105,7 @@ pub struct InitialPipelineState {
pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>, pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
/// A channel to the script thread, if applicable. If this is `Some`, /// A channel to the script thread, if applicable. If this is `Some`,
/// then `parent_info` must also be `Some`. /// then `parent_info` must also be `Some`.
pub script_chan: Option<Sender<ConstellationControlMsg>>, pub script_chan: Option<IpcSender<ConstellationControlMsg>>,
/// Information about the page to load. /// Information about the page to load.
pub load_data: LoadData, pub load_data: LoadData,
/// The ID of the pipeline namespace for this script thread. /// The ID of the pipeline namespace for this script thread.
@ -115,13 +116,14 @@ impl Pipeline {
/// Starts a paint task, layout task, and possibly a script task. /// Starts a paint task, layout task, and possibly a script task.
/// Returns the channels wrapped in a struct. /// Returns the channels wrapped in a struct.
pub fn create<LTF, STF>(state: InitialPipelineState) pub fn create<LTF, STF>(state: InitialPipelineState)
-> (Pipeline, PipelineContent) -> (Pipeline, UnprivilegedPipelineContent, PrivilegedPipelineContent)
where LTF: LayoutTaskFactory, STF: ScriptTaskFactory { where LTF: LayoutTaskFactory, STF: ScriptTaskFactory {
let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel(); let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel();
let (chrome_to_paint_chan, chrome_to_paint_port) = channel(); let (chrome_to_paint_chan, chrome_to_paint_port) = channel();
let (paint_shutdown_chan, paint_shutdown_port) = channel(); let (paint_shutdown_chan, paint_shutdown_port) = ipc::channel().unwrap();
let (layout_shutdown_chan, layout_shutdown_port) = channel(); let (layout_shutdown_chan, layout_shutdown_port) = ipc::channel().unwrap();
let (pipeline_chan, pipeline_port) = ipc::channel().unwrap(); let (pipeline_chan, pipeline_port) = ipc::channel().unwrap();
let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel().unwrap();
let mut pipeline_port = Some(pipeline_port); let mut pipeline_port = Some(pipeline_port);
let failure = Failure { let failure = Failure {
@ -148,6 +150,9 @@ impl Pipeline {
script_to_devtools_chan script_to_devtools_chan
}); });
let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) =
ipc::channel().unwrap();
let (script_chan, script_port) = match state.script_chan { let (script_chan, script_port) = match state.script_chan {
Some(script_chan) => { Some(script_chan) => {
let (containing_pipeline_id, subpage_id) = let (containing_pipeline_id, subpage_id) =
@ -157,10 +162,11 @@ impl Pipeline {
new_pipeline_id: state.id, new_pipeline_id: state.id,
subpage_id: subpage_id, subpage_id: subpage_id,
load_data: state.load_data.clone(), load_data: state.load_data.clone(),
paint_chan: box layout_to_paint_chan.clone() as Box<Any + Send>, paint_chan: layout_to_paint_chan.clone().to_opaque(),
failure: failure, failure: failure,
pipeline_port: mem::replace(&mut pipeline_port, None).unwrap(), pipeline_port: mem::replace(&mut pipeline_port, None).unwrap(),
layout_shutdown_chan: layout_shutdown_chan.clone(), layout_shutdown_chan: layout_shutdown_chan.clone(),
content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(),
}; };
script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)) script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info))
@ -168,11 +174,14 @@ impl Pipeline {
(script_chan, None) (script_chan, None)
} }
None => { None => {
let (script_chan, script_port) = channel(); let (script_chan, script_port) = ipc::channel().unwrap();
(script_chan, Some(script_port)) (script_chan, Some(script_port))
} }
}; };
let (script_content_process_shutdown_chan, script_content_process_shutdown_port) =
ipc::channel().unwrap();
let pipeline = Pipeline::new(state.id, let pipeline = Pipeline::new(state.id,
state.parent_info, state.parent_info,
script_chan.clone(), script_chan.clone(),
@ -184,45 +193,63 @@ impl Pipeline {
state.load_data.url.clone(), state.load_data.url.clone(),
state.window_size); state.window_size);
let pipeline_content = PipelineContent { let unprivileged_pipeline_content = UnprivilegedPipelineContent {
id: state.id, id: state.id,
parent_info: state.parent_info, parent_info: state.parent_info,
constellation_chan: state.constellation_chan, constellation_chan: state.constellation_chan.clone(),
scheduler_chan: state.scheduler_chan, scheduler_chan: state.scheduler_chan,
compositor_proxy: state.compositor_proxy,
devtools_chan: script_to_devtools_chan, devtools_chan: script_to_devtools_chan,
image_cache_task: state.image_cache_task, image_cache_task: state.image_cache_task,
font_cache_task: state.font_cache_task, font_cache_task: state.font_cache_task.clone(),
resource_task: state.resource_task, resource_task: state.resource_task,
storage_task: state.storage_task, storage_task: state.storage_task,
time_profiler_chan: state.time_profiler_chan, time_profiler_chan: state.time_profiler_chan.clone(),
mem_profiler_chan: state.mem_profiler_chan, mem_profiler_chan: state.mem_profiler_chan.clone(),
window_size: window_size, window_size: window_size,
script_chan: script_chan, script_chan: script_chan,
load_data: state.load_data, load_data: state.load_data.clone(),
failure: failure, failure: failure,
script_port: script_port, script_port: script_port,
opts: (*opts::get()).clone(),
layout_to_paint_chan: layout_to_paint_chan, layout_to_paint_chan: layout_to_paint_chan,
chrome_to_paint_chan: chrome_to_paint_chan,
layout_to_paint_port: Some(layout_to_paint_port),
chrome_to_paint_port: Some(chrome_to_paint_port),
pipeline_port: pipeline_port, pipeline_port: pipeline_port,
paint_shutdown_chan: paint_shutdown_chan,
layout_shutdown_chan: layout_shutdown_chan, layout_shutdown_chan: layout_shutdown_chan,
paint_shutdown_chan: paint_shutdown_chan.clone(),
script_to_compositor_chan: script_to_compositor_chan,
pipeline_namespace_id: state.pipeline_namespace_id, pipeline_namespace_id: state.pipeline_namespace_id,
layout_content_process_shutdown_chan: layout_content_process_shutdown_chan,
layout_content_process_shutdown_port: layout_content_process_shutdown_port,
script_content_process_shutdown_chan: script_content_process_shutdown_chan,
script_content_process_shutdown_port: script_content_process_shutdown_port,
}; };
(pipeline, pipeline_content) let privileged_pipeline_content = PrivilegedPipelineContent {
id: state.id,
constellation_chan: state.constellation_chan,
compositor_proxy: state.compositor_proxy,
font_cache_task: state.font_cache_task,
time_profiler_chan: state.time_profiler_chan,
mem_profiler_chan: state.mem_profiler_chan,
load_data: state.load_data,
failure: failure,
layout_to_paint_port: Some(layout_to_paint_port),
chrome_to_paint_chan: chrome_to_paint_chan,
chrome_to_paint_port: Some(chrome_to_paint_port),
paint_shutdown_chan: paint_shutdown_chan,
script_to_compositor_port: Some(script_to_compositor_port),
};
(pipeline, unprivileged_pipeline_content, privileged_pipeline_content)
} }
pub fn new(id: PipelineId, pub fn new(id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>, parent_info: Option<(PipelineId, SubpageId)>,
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
layout_chan: LayoutControlChan, layout_chan: LayoutControlChan,
compositor_proxy: Box<CompositorProxy + 'static + Send>, compositor_proxy: Box<CompositorProxy + 'static + Send>,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>, chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
layout_shutdown_port: Receiver<()>, layout_shutdown_port: IpcReceiver<()>,
paint_shutdown_port: Receiver<()>, paint_shutdown_port: IpcReceiver<()>,
url: Url, url: Url,
size: Option<TypedSize2D<PagePx, f32>>) size: Option<TypedSize2D<PagePx, f32>>)
-> Pipeline { -> Pipeline {
@ -315,13 +342,14 @@ impl Pipeline {
} }
} }
pub struct PipelineContent { #[derive(Deserialize, Serialize)]
pub struct UnprivilegedPipelineContent {
id: PipelineId, id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>, parent_info: Option<(PipelineId, SubpageId)>,
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: ConstellationChan<ConstellationMsg>,
scheduler_chan: IpcSender<TimerEventRequest>, scheduler_chan: IpcSender<TimerEventRequest>,
compositor_proxy: Box<CompositorProxy + Send + 'static>,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
script_to_compositor_chan: IpcSender<ScriptToCompositorMsg>,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask, font_cache_task: FontCacheTask,
resource_task: ResourceTask, resource_task: ResourceTask,
@ -329,39 +357,31 @@ pub struct PipelineContent {
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan, mem_profiler_chan: profile_mem::ProfilerChan,
window_size: Option<WindowSizeData>, window_size: Option<WindowSizeData>,
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
load_data: LoadData, load_data: LoadData,
failure: Failure, failure: Failure,
script_port: Option<Receiver<ConstellationControlMsg>>, script_port: Option<IpcReceiver<ConstellationControlMsg>>,
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>, layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>, opts: Opts,
layout_to_paint_port: Option<Receiver<LayoutToPaintMsg>>, paint_shutdown_chan: IpcSender<()>,
chrome_to_paint_port: Option<Receiver<ChromeToPaintMsg>>,
paint_shutdown_chan: Sender<()>,
pipeline_port: Option<IpcReceiver<LayoutControlMsg>>, pipeline_port: Option<IpcReceiver<LayoutControlMsg>>,
layout_shutdown_chan: Sender<()>,
pipeline_namespace_id: PipelineNamespaceId, pipeline_namespace_id: PipelineNamespaceId,
layout_shutdown_chan: IpcSender<()>,
layout_content_process_shutdown_chan: IpcSender<()>,
layout_content_process_shutdown_port: IpcReceiver<()>,
script_content_process_shutdown_chan: IpcSender<()>,
script_content_process_shutdown_port: IpcReceiver<()>,
} }
impl PipelineContent { impl UnprivilegedPipelineContent {
pub fn start_all<LTF, STF>(mut self) where LTF: LayoutTaskFactory, STF: ScriptTaskFactory { pub fn start_all<LTF, STF>(mut self, wait_for_completion: bool)
where LTF: LayoutTaskFactory, STF: ScriptTaskFactory {
let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>); let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>);
let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel().unwrap();
self.start_paint_task();
let compositor_proxy_for_script_listener_thread =
self.compositor_proxy.clone_compositor_proxy();
thread::spawn(move || {
compositor_task::run_script_listener_thread(
compositor_proxy_for_script_listener_thread,
script_to_compositor_port)
});
ScriptTaskFactory::create(None::<&mut STF>, InitialScriptState { ScriptTaskFactory::create(None::<&mut STF>, InitialScriptState {
id: self.id, id: self.id,
parent_info: self.parent_info, parent_info: self.parent_info,
compositor: script_to_compositor_chan, compositor: self.script_to_compositor_chan.clone(),
control_chan: self.script_chan.clone(), control_chan: self.script_chan.clone(),
control_port: mem::replace(&mut self.script_port, None).unwrap(), control_port: mem::replace(&mut self.script_port, None).unwrap(),
constellation_chan: self.constellation_chan.clone(), constellation_chan: self.constellation_chan.clone(),
@ -375,6 +395,7 @@ impl PipelineContent {
devtools_chan: self.devtools_chan, devtools_chan: self.devtools_chan,
window_size: self.window_size, window_size: self.window_size,
pipeline_namespace_id: self.pipeline_namespace_id, pipeline_namespace_id: self.pipeline_namespace_id,
content_process_shutdown_chan: self.script_content_process_shutdown_chan.clone(),
}, &layout_pair, self.load_data.clone()); }, &layout_pair, self.load_data.clone());
LayoutTaskFactory::create(None::<&mut LTF>, LayoutTaskFactory::create(None::<&mut LTF>,
@ -391,7 +412,49 @@ impl PipelineContent {
self.font_cache_task, self.font_cache_task,
self.time_profiler_chan, self.time_profiler_chan,
self.mem_profiler_chan, self.mem_profiler_chan,
self.layout_shutdown_chan); self.layout_shutdown_chan,
self.layout_content_process_shutdown_chan.clone());
if wait_for_completion {
self.script_content_process_shutdown_port.recv().unwrap();
self.layout_content_process_shutdown_port.recv().unwrap();
}
}
pub fn opts(&self) -> Opts {
self.opts.clone()
}
}
pub struct PrivilegedPipelineContent {
id: PipelineId,
constellation_chan: ConstellationChan<ConstellationMsg>,
compositor_proxy: Box<CompositorProxy + Send + 'static>,
script_to_compositor_port: Option<IpcReceiver<ScriptToCompositorMsg>>,
font_cache_task: FontCacheTask,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
load_data: LoadData,
failure: Failure,
layout_to_paint_port: Option<Receiver<LayoutToPaintMsg>>,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
chrome_to_paint_port: Option<Receiver<ChromeToPaintMsg>>,
paint_shutdown_chan: IpcSender<()>,
}
impl PrivilegedPipelineContent {
pub fn start_all(&mut self) {
self.start_paint_task();
let compositor_proxy_for_script_listener_thread =
self.compositor_proxy.clone_compositor_proxy();
let script_to_compositor_port =
mem::replace(&mut self.script_to_compositor_port, None).unwrap();
thread::spawn(move || {
compositor_task::run_script_listener_thread(
compositor_proxy_for_script_listener_thread,
script_to_compositor_port)
});
} }
pub fn start_paint_task(&mut self) { pub fn start_paint_task(&mut self) {

View file

@ -0,0 +1,38 @@
/* 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/. */
use gaol::platform;
use gaol::profile::{Operation, PathPattern, Profile};
use std::path::PathBuf;
use util::resource_files;
/// Our content process sandbox profile on Mac. As restrictive as possible.
#[cfg(target_os = "macos")]
pub fn content_process_sandbox_profile() -> Profile {
Profile::new(vec![
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))),
Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path())),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/Library/Fonts"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/System/Library/Fonts"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from(
"/System/Library/Frameworks/ApplicationServices.framework/"))),
Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/"))),
Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/Library"))),
Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/System"))),
Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/etc"))),
Operation::SystemInfoRead,
Operation::PlatformSpecific(platform::macos::Operation::MachLookup(
b"com.apple.FontServer".to_vec())),
]).expect("Failed to create sandbox profile!")
}
/// Our content process sandbox profile on Linux. As restrictive as possible.
#[cfg(not(target_os = "macos"))]
pub fn content_process_sandbox_profile() -> Profile {
Profile::new(vec![
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))),
Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path())),
]).expect("Failed to create sandbox profile!")
}

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use font_template::{FontTemplate, FontTemplateDescriptor}; use font_template::{FontTemplate, FontTemplateDescriptor};
use ipc_channel::ipc; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad, ResourceTask, ResponseAction}; use net_traits::{AsyncResponseTarget, PendingAsyncLoad, ResourceTask, ResponseAction};
use platform::font_context::FontContextHandle; use platform::font_context::FontContextHandle;
@ -15,7 +15,7 @@ use platform::font_template::FontTemplateData;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::collections::HashMap; use std::collections::HashMap;
use std::mem; use std::mem;
use std::sync::mpsc::{Sender, Receiver, channel}; use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use string_cache::Atom; use string_cache::Atom;
use style::font_face::Source; use style::font_face::Source;
@ -77,15 +77,17 @@ impl FontFamily {
} }
/// Commands that the FontContext sends to the font cache task. /// Commands that the FontContext sends to the font cache task.
#[derive(Deserialize, Serialize)]
pub enum Command { pub enum Command {
GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>), GetFontTemplate(String, FontTemplateDescriptor, IpcSender<Reply>),
GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>), GetLastResortFontTemplate(FontTemplateDescriptor, IpcSender<Reply>),
AddWebFont(Atom, Source, Sender<()>), AddWebFont(Atom, Source, IpcSender<()>),
AddDownloadedWebFont(LowercaseString, Url, Vec<u8>, Sender<()>), AddDownloadedWebFont(LowercaseString, Url, Vec<u8>, IpcSender<()>),
Exit(Sender<()>), Exit(IpcSender<()>),
} }
/// Reply messages sent from the font cache task to the FontContext caller. /// Reply messages sent from the font cache task to the FontContext caller.
#[derive(Deserialize, Serialize)]
pub enum Reply { pub enum Reply {
GetFontTemplateReply(Option<Arc<FontTemplateData>>), GetFontTemplateReply(Option<Arc<FontTemplateData>>),
} }
@ -93,8 +95,8 @@ pub enum Reply {
/// The font cache task itself. It maintains a list of reference counted /// The font cache task itself. It maintains a list of reference counted
/// font templates that are currently in use. /// font templates that are currently in use.
struct FontCache { struct FontCache {
port: Receiver<Command>, port: IpcReceiver<Command>,
channel_to_self: Sender<Command>, channel_to_self: IpcSender<Command>,
generic_fonts: HashMap<LowercaseString, LowercaseString>, generic_fonts: HashMap<LowercaseString, LowercaseString>,
local_families: HashMap<LowercaseString, FontFamily>, local_families: HashMap<LowercaseString, FontFamily>,
web_families: HashMap<LowercaseString, FontFamily>, web_families: HashMap<LowercaseString, FontFamily>,
@ -269,14 +271,14 @@ impl FontCache {
/// The public interface to the font cache task, used exclusively by /// The public interface to the font cache task, used exclusively by
/// the per-thread/task FontContext structures. /// the per-thread/task FontContext structures.
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub struct FontCacheTask { pub struct FontCacheTask {
chan: Sender<Command>, chan: IpcSender<Command>,
} }
impl FontCacheTask { impl FontCacheTask {
pub fn new(resource_task: ResourceTask) -> FontCacheTask { pub fn new(resource_task: ResourceTask) -> FontCacheTask {
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
let channel_to_self = chan.clone(); let channel_to_self = chan.clone();
spawn_named("FontCacheTask".to_owned(), move || { spawn_named("FontCacheTask".to_owned(), move || {
@ -310,7 +312,7 @@ impl FontCacheTask {
pub fn find_font_template(&self, family: String, desc: FontTemplateDescriptor) pub fn find_font_template(&self, family: String, desc: FontTemplateDescriptor)
-> Option<Arc<FontTemplateData>> { -> Option<Arc<FontTemplateData>> {
let (response_chan, response_port) = channel(); let (response_chan, response_port) = ipc::channel().unwrap();
self.chan.send(Command::GetFontTemplate(family, desc, response_chan)).unwrap(); self.chan.send(Command::GetFontTemplate(family, desc, response_chan)).unwrap();
let reply = response_port.recv().unwrap(); let reply = response_port.recv().unwrap();
@ -325,7 +327,7 @@ impl FontCacheTask {
pub fn last_resort_font_template(&self, desc: FontTemplateDescriptor) pub fn last_resort_font_template(&self, desc: FontTemplateDescriptor)
-> Arc<FontTemplateData> { -> Arc<FontTemplateData> {
let (response_chan, response_port) = channel(); let (response_chan, response_port) = ipc::channel().unwrap();
self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan)).unwrap(); self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan)).unwrap();
let reply = response_port.recv().unwrap(); let reply = response_port.recv().unwrap();
@ -337,12 +339,12 @@ impl FontCacheTask {
} }
} }
pub fn add_web_font(&self, family: Atom, src: Source, sender: Sender<()>) { pub fn add_web_font(&self, family: Atom, src: Source, sender: IpcSender<()>) {
self.chan.send(Command::AddWebFont(family, src, sender)).unwrap(); self.chan.send(Command::AddWebFont(family, src, sender)).unwrap();
} }
pub fn exit(&self) { pub fn exit(&self) {
let (response_chan, response_port) = channel(); let (response_chan, response_port) = ipc::channel().unwrap();
self.chan.send(Command::Exit(response_chan)).unwrap(); self.chan.send(Command::Exit(response_chan)).unwrap();
response_port.recv().unwrap(); response_port.recv().unwrap();
} }

View file

@ -14,7 +14,7 @@ use style::computed_values::{font_stretch, font_weight};
/// to be expanded or refactored when we support more of the font styling parameters. /// to be expanded or refactored when we support more of the font styling parameters.
/// ///
/// NB: If you change this, you will need to update `style::properties::compute_font_hash()`. /// NB: If you change this, you will need to update `style::properties::compute_font_hash()`.
#[derive(Clone, Copy, Eq, Hash)] #[derive(Clone, Copy, Eq, Hash, Deserialize, Serialize)]
pub struct FontTemplateDescriptor { pub struct FontTemplateDescriptor {
pub weight: font_weight::T, pub weight: font_weight::T,
pub stretch: font_stretch::T, pub stretch: font_stretch::T,

View file

@ -36,8 +36,7 @@ use std::sync::mpsc::{Receiver, Select, Sender, channel};
use url::Url; use url::Url;
use util::geometry::{ExpandToPixelBoundaries, ZERO_POINT}; use util::geometry::{ExpandToPixelBoundaries, ZERO_POINT};
use util::opts; use util::opts;
use util::task::spawn_named; use util::task;
use util::task::spawn_named_with_send_on_failure;
use util::task_state; use util::task_state;
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] #[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
@ -255,9 +254,11 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
failure_msg: Failure, failure_msg: Failure,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: Sender<()>) { shutdown_chan: IpcSender<()>) {
let ConstellationChan(c) = constellation_chan.clone(); let ConstellationChan(c) = constellation_chan.clone();
spawn_named_with_send_on_failure(format!("PaintTask {:?}", id), task_state::PAINT, move || { task::spawn_named_with_send_on_failure(format!("PaintTask {:?}", id),
task_state::PAINT,
move || {
{ {
// Ensures that the paint task and graphics context are destroyed before the // Ensures that the paint task and graphics context are destroyed before the
// shutdown message. // shutdown message.
@ -572,7 +573,7 @@ impl WorkerThreadProxy {
let (to_worker_sender, to_worker_receiver) = channel(); let (to_worker_sender, to_worker_receiver) = channel();
let font_cache_task = font_cache_task.clone(); let font_cache_task = font_cache_task.clone();
let time_profiler_chan = time_profiler_chan.clone(); let time_profiler_chan = time_profiler_chan.clone();
spawn_named("PaintWorker".to_owned(), move || { task::spawn_named("PaintWorker".to_owned(), move || {
let mut worker_thread = WorkerThread::new(from_worker_sender, let mut worker_thread = WorkerThread::new(from_worker_sender,
to_worker_receiver, to_worker_receiver,
native_display, native_display,

View file

@ -70,7 +70,7 @@ use util::ipc::OptionalIpcSender;
use util::logical_geometry::LogicalPoint; use util::logical_geometry::LogicalPoint;
use util::mem::HeapSizeOf; use util::mem::HeapSizeOf;
use util::opts; use util::opts;
use util::task::spawn_named_with_send_on_failure; use util::task;
use util::task_state; use util::task_state;
use util::workqueue::WorkQueue; use util::workqueue::WorkQueue;
use wrapper::{LayoutDocument, LayoutElement, LayoutNode, ServoLayoutNode}; use wrapper::{LayoutDocument, LayoutElement, LayoutNode, ServoLayoutNode};
@ -137,13 +137,13 @@ pub struct LayoutTask {
font_cache_receiver: Receiver<()>, font_cache_receiver: Receiver<()>,
/// The channel on which the font cache can send messages to us. /// The channel on which the font cache can send messages to us.
font_cache_sender: Sender<()>, font_cache_sender: IpcSender<()>,
/// The channel on which messages can be sent to the constellation. /// The channel on which messages can be sent to the constellation.
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: ConstellationChan<ConstellationMsg>,
/// The channel on which messages can be sent to the script task. /// The channel on which messages can be sent to the script task.
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
/// The channel on which messages can be sent to the painting task. /// The channel on which messages can be sent to the painting task.
paint_chan: OptionalIpcSender<LayoutToPaintMsg>, paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
@ -219,17 +219,18 @@ impl LayoutTaskFactory for LayoutTask {
pipeline_port: IpcReceiver<LayoutControlMsg>, pipeline_port: IpcReceiver<LayoutControlMsg>,
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: ConstellationChan<ConstellationMsg>,
failure_msg: Failure, failure_msg: Failure,
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
paint_chan: OptionalIpcSender<LayoutToPaintMsg>, paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask, font_cache_task: FontCacheTask,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: Sender<()>) { shutdown_chan: IpcSender<()>,
content_process_shutdown_chan: IpcSender<()>) {
let ConstellationChan(con_chan) = constellation_chan.clone(); let ConstellationChan(con_chan) = constellation_chan.clone();
spawn_named_with_send_on_failure(format!("LayoutTask {:?}", id), task::spawn_named_with_send_on_failure(format!("LayoutTask {:?}", id),
task_state::LAYOUT, task_state::LAYOUT,
move || { move || {
{ // Ensures layout task is destroyed before we send shutdown message { // Ensures layout task is destroyed before we send shutdown message
let sender = chan.sender(); let sender = chan.sender();
let layout = LayoutTask::new(id, let layout = LayoutTask::new(id,
@ -250,7 +251,8 @@ impl LayoutTaskFactory for LayoutTask {
layout.start(); layout.start();
}, reporter_name, sender, Msg::CollectReports); }, reporter_name, sender, Msg::CollectReports);
} }
shutdown_chan.send(()).unwrap(); let _ = shutdown_chan.send(());
let _ = content_process_shutdown_chan.send(());
}, ConstellationMsg::Failure(failure_msg), con_chan); }, ConstellationMsg::Failure(failure_msg), con_chan);
} }
} }
@ -318,12 +320,12 @@ impl<'a, 'b: 'a> RwData<'a, 'b> {
fn add_font_face_rules(stylesheet: &Stylesheet, fn add_font_face_rules(stylesheet: &Stylesheet,
device: &Device, device: &Device,
font_cache_task: &FontCacheTask, font_cache_task: &FontCacheTask,
font_cache_sender: &Sender<()>, font_cache_sender: &IpcSender<()>,
outstanding_web_fonts_counter: &Arc<AtomicUsize>) { outstanding_web_fonts_counter: &Arc<AtomicUsize>) {
for font_face in stylesheet.effective_rules(&device).font_face() { for font_face in stylesheet.effective_rules(&device).font_face() {
for source in &font_face.sources { for source in &font_face.sources {
if opts::get().load_webfonts_synchronously { if opts::get().load_webfonts_synchronously {
let (sender, receiver) = channel(); let (sender, receiver) = ipc::channel().unwrap();
font_cache_task.add_web_font(font_face.family.clone(), font_cache_task.add_web_font(font_face.family.clone(),
(*source).clone(), (*source).clone(),
sender); sender);
@ -346,7 +348,7 @@ impl LayoutTask {
port: Receiver<Msg>, port: Receiver<Msg>,
pipeline_port: IpcReceiver<LayoutControlMsg>, pipeline_port: IpcReceiver<LayoutControlMsg>,
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: ConstellationChan<ConstellationMsg>,
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
paint_chan: OptionalIpcSender<LayoutToPaintMsg>, paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask, font_cache_task: FontCacheTask,
@ -375,7 +377,10 @@ impl LayoutTask {
let image_cache_receiver = let image_cache_receiver =
ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_image_cache_receiver); ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_image_cache_receiver);
let (font_cache_sender, font_cache_receiver) = channel(); // Ask the router to proxy IPC messages from the font cache task to the layout thread.
let (ipc_font_cache_sender, ipc_font_cache_receiver) = ipc::channel().unwrap();
let font_cache_receiver =
ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_font_cache_receiver);
let stylist = box Stylist::new(device); let stylist = box Stylist::new(device);
let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0)); let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0));
@ -383,7 +388,7 @@ impl LayoutTask {
add_font_face_rules(stylesheet, add_font_face_rules(stylesheet,
&stylist.device, &stylist.device,
&font_cache_task, &font_cache_task,
&font_cache_sender, &ipc_font_cache_sender,
&outstanding_web_fonts_counter); &outstanding_web_fonts_counter);
} }
@ -404,7 +409,7 @@ impl LayoutTask {
image_cache_receiver: image_cache_receiver, image_cache_receiver: image_cache_receiver,
image_cache_sender: ImageCacheChan(ipc_image_cache_sender), image_cache_sender: ImageCacheChan(ipc_image_cache_sender),
font_cache_receiver: font_cache_receiver, font_cache_receiver: font_cache_receiver,
font_cache_sender: font_cache_sender, font_cache_sender: ipc_font_cache_sender,
canvas_layers_receiver: canvas_layers_receiver, canvas_layers_receiver: canvas_layers_receiver,
canvas_layers_sender: canvas_layers_sender, canvas_layers_sender: canvas_layers_sender,
parallel_traversal: parallel_traversal, parallel_traversal: parallel_traversal,
@ -668,14 +673,13 @@ impl LayoutTask {
info.constellation_chan, info.constellation_chan,
info.failure, info.failure,
info.script_chan.clone(), info.script_chan.clone(),
*info.paint_chan info.paint_chan.to::<LayoutToPaintMsg>(),
.downcast::<OptionalIpcSender<LayoutToPaintMsg>>()
.unwrap(),
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.font_cache_task.clone(), self.font_cache_task.clone(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(), self.mem_profiler_chan.clone(),
info.layout_shutdown_chan); info.layout_shutdown_chan,
info.content_process_shutdown_chan);
} }
/// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is /// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is

View file

@ -29,7 +29,6 @@ use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
use net_traits::image_cache_task::ImageCacheTask; use net_traits::image_cache_task::ImageCacheTask;
use profile_traits::{mem, time}; use profile_traits::{mem, time};
use script_traits::{LayoutControlMsg, ConstellationControlMsg, OpaqueScriptLayoutChannel}; use script_traits::{LayoutControlMsg, ConstellationControlMsg, OpaqueScriptLayoutChannel};
use std::sync::mpsc::Sender;
use url::Url; use url::Url;
use util::ipc::OptionalIpcSender; use util::ipc::OptionalIpcSender;
@ -49,11 +48,12 @@ pub trait LayoutTaskFactory {
pipeline_port: IpcReceiver<LayoutControlMsg>, pipeline_port: IpcReceiver<LayoutControlMsg>,
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: ConstellationChan<ConstellationMsg>,
failure_msg: Failure, failure_msg: Failure,
script_chan: Sender<ConstellationControlMsg>, script_chan: IpcSender<ConstellationControlMsg>,
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>, layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask, font_cache_task: FontCacheTask,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: Sender<()>); shutdown_chan: IpcSender<()>,
content_process_shutdown_chan: IpcSender<()>);
} }

View file

@ -11,13 +11,14 @@ use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D}; use euclid::size::{Size2D, TypedSize2D};
use hyper::header::Headers; use hyper::header::Headers;
use hyper::method::Method; use hyper::method::Method;
use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender, IpcSharedMemory};
use layers::geometry::DevicePixel; use layers::geometry::DevicePixel;
use offscreen_gl_context::GLContextAttributes; use offscreen_gl_context::GLContextAttributes;
use serde::{Deserialize, Serialize};
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::sync::mpsc::{Receiver, Sender, channel}; use std::sync::mpsc::channel;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use url::Url; use url::Url;
use util::cursor::Cursor; use util::cursor::Cursor;
@ -25,16 +26,17 @@ use util::geometry::{PagePx, ViewportPx};
use util::mem::HeapSizeOf; use util::mem::HeapSizeOf;
use webdriver_msg::{LoadStatus, WebDriverScriptCommand}; use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
pub struct ConstellationChan<T>(pub Sender<T>); #[derive(Deserialize, Serialize)]
pub struct ConstellationChan<T: Deserialize + Serialize>(pub IpcSender<T>);
impl<T> ConstellationChan<T> { impl<T: Deserialize + Serialize> ConstellationChan<T> {
pub fn new() -> (Receiver<T>, ConstellationChan<T>) { pub fn new() -> (IpcReceiver<T>, ConstellationChan<T>) {
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
(port, ConstellationChan(chan)) (port, ConstellationChan(chan))
} }
} }
impl<T> Clone for ConstellationChan<T> { impl<T: Serialize + Deserialize> Clone for ConstellationChan<T> {
fn clone(&self) -> ConstellationChan<T> { fn clone(&self) -> ConstellationChan<T> {
ConstellationChan(self.0.clone()) ConstellationChan(self.0.clone())
} }

View file

@ -100,6 +100,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element", ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element",
ProfilerCategory::ScriptSetViewport => "Script Set Viewport", ProfilerCategory::ScriptSetViewport => "Script Set Viewport",
ProfilerCategory::ScriptTimerEvent => "Script Timer Event", ProfilerCategory::ScriptTimerEvent => "Script Timer Event",
ProfilerCategory::ScriptStylesheetLoad => "Script Stylesheet Load",
ProfilerCategory::ScriptWebSocketEvent => "Script Web Socket Event", ProfilerCategory::ScriptWebSocketEvent => "Script Web Socket Event",
ProfilerCategory::ScriptWorkerEvent => "Script Worker Event", ProfilerCategory::ScriptWorkerEvent => "Script Worker Event",
ProfilerCategory::ApplicationHeartbeat => "Application Heartbeat", ProfilerCategory::ApplicationHeartbeat => "Application Heartbeat",

View file

@ -25,7 +25,7 @@ impl<T> OpaqueSender<T> for Sender<T> {
/// Front-end representation of the profiler used to communicate with the /// Front-end representation of the profiler used to communicate with the
/// profiler. /// profiler.
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub struct ProfilerChan(pub IpcSender<ProfilerMsg>); pub struct ProfilerChan(pub IpcSender<ProfilerMsg>);
impl ProfilerChan { impl ProfilerChan {

View file

@ -60,15 +60,16 @@ pub enum ProfilerCategory {
ScriptDevtoolsMsg, ScriptDevtoolsMsg,
ScriptDocumentEvent, ScriptDocumentEvent,
ScriptDomEvent, ScriptDomEvent,
ScriptEvent,
ScriptFileRead, ScriptFileRead,
ScriptImageCacheMsg, ScriptImageCacheMsg,
ScriptInputEvent, ScriptInputEvent,
ScriptNetworkEvent, ScriptNetworkEvent,
ScriptResize, ScriptResize,
ScriptEvent,
ScriptUpdateReplacedElement,
ScriptSetViewport, ScriptSetViewport,
ScriptTimerEvent, ScriptTimerEvent,
ScriptStylesheetLoad,
ScriptUpdateReplacedElement,
ScriptWebSocketEvent, ScriptWebSocketEvent,
ScriptWorkerEvent, ScriptWorkerEvent,
ApplicationHeartbeat, ApplicationHeartbeat,

View file

@ -53,7 +53,7 @@ use js::jsval::JSVal;
use js::rust::Runtime; use js::rust::Runtime;
use layout_interface::{LayoutChan, LayoutRPC}; use layout_interface::{LayoutChan, LayoutRPC};
use libc; use libc;
use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::{ConstellationChan, ScriptMsg};
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData, WorkerId}; use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData, WorkerId};
use net_traits::Metadata; use net_traits::Metadata;
use net_traits::image::base::Image; use net_traits::image::base::Image;
@ -275,7 +275,6 @@ no_jsmanaged_fields!(WorkerId);
no_jsmanaged_fields!(QuirksMode); no_jsmanaged_fields!(QuirksMode);
no_jsmanaged_fields!(Runtime); no_jsmanaged_fields!(Runtime);
no_jsmanaged_fields!(Headers, Method); no_jsmanaged_fields!(Headers, Method);
no_jsmanaged_fields!(ConstellationChan<ConstellationMsg>);
no_jsmanaged_fields!(LayoutChan); no_jsmanaged_fields!(LayoutChan);
no_jsmanaged_fields!(WindowProxyHandler); no_jsmanaged_fields!(WindowProxyHandler);
no_jsmanaged_fields!(UntrustedNodeAddress); no_jsmanaged_fields!(UntrustedNodeAddress);
@ -299,6 +298,13 @@ no_jsmanaged_fields!(AttrIdentifier);
no_jsmanaged_fields!(AttrValue); no_jsmanaged_fields!(AttrValue);
no_jsmanaged_fields!(ElementSnapshot); no_jsmanaged_fields!(ElementSnapshot);
impl JSTraceable for ConstellationChan<ScriptMsg> {
#[inline]
fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
impl JSTraceable for Box<ScriptChan + Send> { impl JSTraceable for Box<ScriptChan + Send> {
#[inline] #[inline]
fn trace(&self, _trc: *mut JSTracer) { fn trace(&self, _trc: *mut JSTracer) {

View file

@ -29,6 +29,8 @@ use string_cache::Atom;
use style::animation::PropertyAnimation; use style::animation::PropertyAnimation;
use style::stylesheets::Stylesheet; use style::stylesheets::Stylesheet;
use url::Url; use url::Url;
use util::ipc::OptionalOpaqueIpcSender;
pub use dom::node::TrustedNodeAddress; pub use dom::node::TrustedNodeAddress;
/// Asynchronous messages that script can send to layout. /// Asynchronous messages that script can send to layout.
@ -254,8 +256,9 @@ pub struct NewLayoutTaskInfo {
pub pipeline_port: IpcReceiver<LayoutControlMsg>, pub pipeline_port: IpcReceiver<LayoutControlMsg>,
pub constellation_chan: ConstellationChan<ConstellationMsg>, pub constellation_chan: ConstellationChan<ConstellationMsg>,
pub failure: Failure, pub failure: Failure,
pub script_chan: Sender<ConstellationControlMsg>, pub script_chan: IpcSender<ConstellationControlMsg>,
pub image_cache_task: ImageCacheTask, pub image_cache_task: ImageCacheTask,
pub paint_chan: Box<Any + Send>, pub paint_chan: OptionalOpaqueIpcSender,
pub layout_shutdown_chan: Sender<()>, pub layout_shutdown_chan: IpcSender<()>,
pub content_process_shutdown_chan: IpcSender<()>,
} }

View file

@ -104,7 +104,7 @@ use time::{Tm, now};
use url::{Url, UrlParser}; use url::{Url, UrlParser};
use util::opts; use util::opts;
use util::str::DOMString; use util::str::DOMString;
use util::task::spawn_named_with_send_on_failure; use util::task;
use util::task_state; use util::task_state;
use webdriver_handlers; use webdriver_handlers;
@ -232,8 +232,9 @@ pub enum ScriptTaskEventCategory {
Resize, Resize,
ScriptEvent, ScriptEvent,
TimerEvent, TimerEvent,
UpdateReplacedElement,
SetViewport, SetViewport,
StylesheetLoad,
UpdateReplacedElement,
WebSocketEvent, WebSocketEvent,
WorkerEvent, WorkerEvent,
} }
@ -396,7 +397,7 @@ pub struct ScriptTask {
chan: MainThreadScriptChan, chan: MainThreadScriptChan,
/// A channel to hand out to tasks that need to respond to a message from the script task. /// A channel to hand out to tasks that need to respond to a message from the script task.
control_chan: Sender<ConstellationControlMsg>, control_chan: IpcSender<ConstellationControlMsg>,
/// The port on which the constellation and layout tasks can communicate with the /// The port on which the constellation and layout tasks can communicate with the
/// script task. /// script task.
@ -438,6 +439,8 @@ pub struct ScriptTask {
scheduler_chan: IpcSender<TimerEventRequest>, scheduler_chan: IpcSender<TimerEventRequest>,
timer_event_chan: Sender<TimerEvent>, timer_event_chan: Sender<TimerEvent>,
timer_event_port: Receiver<TimerEvent>, timer_event_port: Receiver<TimerEvent>,
content_process_shutdown_chan: IpcSender<()>,
} }
/// In the event of task failure, all data on the stack runs its destructor. However, there /// In the event of task failure, all data on the stack runs its destructor. However, there
@ -484,7 +487,8 @@ impl ScriptTaskFactory for ScriptTask {
ScriptLayoutChan::new(chan, port) ScriptLayoutChan::new(chan, port)
} }
fn clone_layout_channel(_phantom: Option<&mut ScriptTask>, pair: &OpaqueScriptLayoutChannel) -> Box<Any + Send> { fn clone_layout_channel(_phantom: Option<&mut ScriptTask>, pair: &OpaqueScriptLayoutChannel)
-> Box<Any + Send> {
box pair.sender() as Box<Any + Send> box pair.sender() as Box<Any + Send>
} }
@ -496,9 +500,10 @@ impl ScriptTaskFactory for ScriptTask {
let (script_chan, script_port) = channel(); let (script_chan, script_port) = channel();
let layout_chan = LayoutChan(layout_chan.sender()); let layout_chan = LayoutChan(layout_chan.sender());
let failure_info = state.failure_info; let failure_info = state.failure_info;
spawn_named_with_send_on_failure(format!("ScriptTask {:?}", state.id), task_state::SCRIPT, move || { task::spawn_named_with_send_on_failure(format!("ScriptTask {:?}", state.id),
task_state::SCRIPT,
move || {
PipelineNamespace::install(state.pipeline_namespace_id); PipelineNamespace::install(state.pipeline_namespace_id);
let roots = RootCollection::new(); let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots); let _stack_roots_tls = StackRootTLS::new(&roots);
let chan = MainThreadScriptChan(script_chan); let chan = MainThreadScriptChan(script_chan);
@ -524,6 +529,7 @@ impl ScriptTaskFactory for ScriptTask {
let reporter_name = format!("script-reporter-{}", id); let reporter_name = format!("script-reporter-{}", id);
mem_profiler_chan.run_with_memory_reporting(|| { mem_profiler_chan.run_with_memory_reporting(|| {
script_task.start(); script_task.start();
let _ = script_task.content_process_shutdown_chan.send(());
}, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports); }, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports);
// This must always be the very last operation performed before the task completes // This must always be the very last operation performed before the task completes
@ -636,6 +642,9 @@ impl ScriptTask {
let (timer_event_chan, timer_event_port) = channel(); let (timer_event_chan, timer_event_port) = channel();
// Ask the router to proxy IPC messages from the control port to us.
let control_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(state.control_port);
ScriptTask { ScriptTask {
page: DOMRefCell::new(None), page: DOMRefCell::new(None),
incomplete_loads: DOMRefCell::new(vec!()), incomplete_loads: DOMRefCell::new(vec!()),
@ -650,7 +659,7 @@ impl ScriptTask {
port: port, port: port,
chan: chan, chan: chan,
control_chan: state.control_chan, control_chan: state.control_chan,
control_port: state.control_port, control_port: control_port,
constellation_chan: state.constellation_chan, constellation_chan: state.constellation_chan,
compositor: DOMRefCell::new(state.compositor), compositor: DOMRefCell::new(state.compositor),
time_profiler_chan: state.time_profiler_chan, time_profiler_chan: state.time_profiler_chan,
@ -667,6 +676,8 @@ impl ScriptTask {
scheduler_chan: state.scheduler_chan, scheduler_chan: state.scheduler_chan,
timer_event_chan: timer_event_chan, timer_event_chan: timer_event_chan,
timer_event_port: timer_event_port, timer_event_port: timer_event_port,
content_process_shutdown_chan: state.content_process_shutdown_chan,
} }
} }
@ -940,7 +951,10 @@ impl ScriptTask {
ScriptTaskEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent, ScriptTaskEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent,
ScriptTaskEventCategory::Resize => ProfilerCategory::ScriptResize, ScriptTaskEventCategory::Resize => ProfilerCategory::ScriptResize,
ScriptTaskEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent, ScriptTaskEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
ScriptTaskEventCategory::UpdateReplacedElement => ProfilerCategory::ScriptUpdateReplacedElement, ScriptTaskEventCategory::UpdateReplacedElement => {
ProfilerCategory::ScriptUpdateReplacedElement
}
ScriptTaskEventCategory::StylesheetLoad => ProfilerCategory::ScriptStylesheetLoad,
ScriptTaskEventCategory::SetViewport => ProfilerCategory::ScriptSetViewport, ScriptTaskEventCategory::SetViewport => ProfilerCategory::ScriptSetViewport,
ScriptTaskEventCategory::TimerEvent => ProfilerCategory::ScriptTimerEvent, ScriptTaskEventCategory::TimerEvent => ProfilerCategory::ScriptTimerEvent,
ScriptTaskEventCategory::WebSocketEvent => ProfilerCategory::ScriptWebSocketEvent, ScriptTaskEventCategory::WebSocketEvent => ProfilerCategory::ScriptWebSocketEvent,
@ -1185,6 +1199,7 @@ impl ScriptTask {
failure, failure,
pipeline_port, pipeline_port,
layout_shutdown_chan, layout_shutdown_chan,
content_process_shutdown_chan,
} = new_layout_info; } = new_layout_info;
let layout_pair = ScriptTask::create_layout_channel(None::<&mut ScriptTask>); let layout_pair = ScriptTask::create_layout_channel(None::<&mut ScriptTask>);
@ -1204,6 +1219,7 @@ impl ScriptTask {
script_chan: self.control_chan.clone(), script_chan: self.control_chan.clone(),
image_cache_task: self.image_cache_task.clone(), image_cache_task: self.image_cache_task.clone(),
layout_shutdown_chan: layout_shutdown_chan, layout_shutdown_chan: layout_shutdown_chan,
content_process_shutdown_chan: content_process_shutdown_chan,
}; };
let page = self.root_page(); let page = self.root_page();

View file

@ -41,7 +41,7 @@ use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::StorageTask; use net_traits::storage_task::StorageTask;
use profile_traits::mem; use profile_traits::mem;
use std::any::Any; use std::any::Any;
use std::sync::mpsc::{Receiver, Sender}; use util::ipc::OptionalOpaqueIpcSender;
use util::mem::HeapSizeOf; use util::mem::HeapSizeOf;
/// The address of a node. Layout sends these back. They must be validated via /// The address of a node. Layout sends these back. They must be validated via
@ -68,6 +68,7 @@ pub enum LayoutControlMsg {
} }
/// The initial data associated with a newly-created framed pipeline. /// The initial data associated with a newly-created framed pipeline.
#[derive(Deserialize, Serialize)]
pub struct NewLayoutInfo { pub struct NewLayoutInfo {
/// Id of the parent of this new pipeline. /// Id of the parent of this new pipeline.
pub containing_pipeline_id: PipelineId, pub containing_pipeline_id: PipelineId,
@ -77,21 +78,21 @@ pub struct NewLayoutInfo {
pub subpage_id: SubpageId, pub subpage_id: SubpageId,
/// Network request data which will be initiated by the script task. /// Network request data which will be initiated by the script task.
pub load_data: LoadData, pub load_data: LoadData,
/// The paint channel, cast to `Box<Any>`. /// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an
/// /// `Sender<LayoutToPaintMsg>`.
/// TODO(pcwalton): When we convert this to use IPC, this will need to become an pub paint_chan: OptionalOpaqueIpcSender,
/// `IpcAnySender`.
pub paint_chan: Box<Any + Send>,
/// Information on what to do on task failure. /// Information on what to do on task failure.
pub failure: Failure, pub failure: Failure,
/// A port on which layout can receive messages from the pipeline. /// A port on which layout can receive messages from the pipeline.
pub pipeline_port: IpcReceiver<LayoutControlMsg>, pub pipeline_port: IpcReceiver<LayoutControlMsg>,
/// A shutdown channel so that layout can notify others when it's done. /// A shutdown channel so that layout can notify others when it's done.
pub layout_shutdown_chan: Sender<()>, pub layout_shutdown_chan: IpcSender<()>,
/// A shutdown channel so that layout can tell the content process to shut down when it's done.
pub content_process_shutdown_chan: IpcSender<()>,
} }
/// Used to determine if a script has any pending asynchronous activity. /// Used to determine if a script has any pending asynchronous activity.
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum ScriptState { pub enum ScriptState {
/// The document has been loaded. /// The document has been loaded.
DocumentLoaded, DocumentLoaded,
@ -100,6 +101,7 @@ pub enum ScriptState {
} }
/// Messages sent from the constellation or layout to the script task. /// Messages sent from the constellation or layout to the script task.
#[derive(Deserialize, Serialize)]
pub enum ConstellationControlMsg { pub enum ConstellationControlMsg {
/// Gives a channel and ID to a layout task, as well as the ID of that layout's parent /// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
AttachLayout(NewLayoutInfo), AttachLayout(NewLayoutInfo),
@ -135,11 +137,11 @@ pub enum ConstellationControlMsg {
/// reflowed. /// reflowed.
WebFontLoaded(PipelineId), WebFontLoaded(PipelineId),
/// Get the current state of the script task for a given pipeline. /// Get the current state of the script task for a given pipeline.
GetCurrentState(Sender<ScriptState>, PipelineId), GetCurrentState(IpcSender<ScriptState>, PipelineId),
} }
/// The mouse button involved in the event. /// The mouse button involved in the event.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum MouseButton { pub enum MouseButton {
/// The left mouse button. /// The left mouse button.
Left, Left,
@ -150,7 +152,7 @@ pub enum MouseButton {
} }
/// The type of input represented by a multi-touch event. /// The type of input represented by a multi-touch event.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum TouchEventType { pub enum TouchEventType {
/// A new touch point came in contact with the screen. /// A new touch point came in contact with the screen.
Down, Down,
@ -165,10 +167,11 @@ pub enum TouchEventType {
/// An opaque identifier for a touch point. /// An opaque identifier for a touch point.
/// ///
/// http://w3c.github.io/touch-events/#widl-Touch-identifier /// http://w3c.github.io/touch-events/#widl-Touch-identifier
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct TouchId(pub i32); pub struct TouchId(pub i32);
/// Events from the compositor that the script task needs to know about /// Events from the compositor that the script task needs to know about
#[derive(Deserialize, Serialize)]
pub enum CompositorEvent { pub enum CompositorEvent {
/// The window was resized. /// The window was resized.
ResizeEvent(WindowSizeData), ResizeEvent(WindowSizeData),
@ -250,9 +253,9 @@ pub struct InitialScriptState {
/// The compositor. /// The compositor.
pub compositor: IpcSender<ScriptToCompositorMsg>, pub compositor: IpcSender<ScriptToCompositorMsg>,
/// A channel with which messages can be sent to us (the script task). /// A channel with which messages can be sent to us (the script task).
pub control_chan: Sender<ConstellationControlMsg>, pub control_chan: IpcSender<ConstellationControlMsg>,
/// A port on which messages sent by the constellation to script can be received. /// A port on which messages sent by the constellation to script can be received.
pub control_port: Receiver<ConstellationControlMsg>, pub control_port: IpcReceiver<ConstellationControlMsg>,
/// A channel on which messages can be sent to the constellation from script. /// A channel on which messages can be sent to the constellation from script.
pub constellation_chan: ConstellationChan<ConstellationMsg>, pub constellation_chan: ConstellationChan<ConstellationMsg>,
/// A channel to schedule timer events. /// A channel to schedule timer events.
@ -275,8 +278,14 @@ pub struct InitialScriptState {
pub window_size: Option<WindowSizeData>, pub window_size: Option<WindowSizeData>,
/// The ID of the pipeline namespace for this script thread. /// The ID of the pipeline namespace for this script thread.
pub pipeline_namespace_id: PipelineNamespaceId, pub pipeline_namespace_id: PipelineNamespaceId,
/// A ping will be sent on this channel once the script thread shuts down.
pub content_process_shutdown_chan: IpcSender<()>,
} }
/// Encapsulates external communication with the script task.
#[derive(Clone, Deserialize, Serialize)]
pub struct ScriptControlChan(pub IpcSender<ConstellationControlMsg>);
/// This trait allows creating a `ScriptTask` without depending on the `script` /// This trait allows creating a `ScriptTask` without depending on the `script`
/// crate. /// crate.
pub trait ScriptTaskFactory { pub trait ScriptTaskFactory {

View file

@ -11,11 +11,13 @@ dependencies = [
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gfx_tests 0.0.1", "gfx_tests 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin_app 0.0.1", "glutin_app 0.0.1",
"image 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout 0.0.1", "layout 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -261,6 +263,7 @@ dependencies = [
"core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@ -268,6 +271,7 @@ dependencies = [
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout_traits 0.0.1", "layout_traits 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1", "msg 0.0.1",
"net_traits 0.0.1", "net_traits 0.0.1",
@ -276,6 +280,8 @@ dependencies = [
"plugins 0.0.1", "plugins 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1", "style_traits 0.0.1",
"time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
@ -600,6 +606,16 @@ dependencies = [
"mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "gaol"
version = "0.0.1"
source = "git+https://github.com/pcwalton/gaol#71865ff8a1824cbc1cbee4d388d56c5ba1b5ffc2"
dependencies = [
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.16" version = "0.3.16"

View file

@ -129,6 +129,12 @@ features = [ "serde_serialization" ]
version = "0.3" version = "0.3"
features = ["plugins"] features = ["plugins"]
[dependencies.gaol]
git = "https://github.com/pcwalton/gaol"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies.layers] [dependencies.layers]
git = "https://github.com/servo/rust-layers" git = "https://github.com/servo/rust-layers"
features = ["plugins"] features = ["plugins"]

View file

@ -17,6 +17,8 @@
// The `Browser` is fed events from a generic type that implements the // The `Browser` is fed events from a generic type that implements the
// `WindowMethods` trait. // `WindowMethods` trait.
extern crate gaol;
#[macro_use] #[macro_use]
extern crate util as _util; extern crate util as _util;
@ -29,6 +31,7 @@ mod export {
extern crate euclid; extern crate euclid;
extern crate gfx; extern crate gfx;
extern crate gleam; extern crate gleam;
extern crate ipc_channel;
extern crate layers; extern crate layers;
extern crate layout; extern crate layout;
extern crate msg; extern crate msg;
@ -48,22 +51,25 @@ extern crate libc;
extern crate webdriver_server; extern crate webdriver_server;
#[cfg(feature = "webdriver")] #[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: msg::constellation_msg::ConstellationChan<ConstellationMsg>) { fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
webdriver_server::start_server(port, constellation.clone()); webdriver_server::start_server(port, constellation);
} }
#[cfg(not(feature = "webdriver"))] #[cfg(not(feature = "webdriver"))]
fn webdriver(_port: u16, _constellation: msg::constellation_msg::ConstellationChan<ConstellationMsg>) { } fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }
use compositing::CompositorEventListener; use compositing::CompositorEventListener;
use compositing::compositor_task::InitialCompositorState; use compositing::compositor_task::InitialCompositorState;
use compositing::constellation::InitialConstellationState; use compositing::constellation::InitialConstellationState;
use compositing::pipeline::UnprivilegedPipelineContent;
use compositing::sandboxing;
use compositing::windowing::WindowEvent; use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods; use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorTask, Constellation}; use compositing::{CompositorProxy, CompositorTask, Constellation};
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_task::FontCacheTask; use gfx::font_cache_task::FontCacheTask;
use ipc_channel::ipc::{self, IpcSender};
use msg::constellation_msg::CompositorMsg as ConstellationMsg; use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::ConstellationChan;
use net::image_cache_task::new_image_cache_task; use net::image_cache_task::new_image_cache_task;
use net::resource_task::new_resource_task; use net::resource_task::new_resource_task;
use net::storage_task::StorageTaskFactory; use net::storage_task::StorageTaskFactory;
@ -86,6 +92,7 @@ pub use export::devtools_traits;
pub use export::euclid; pub use export::euclid;
pub use export::gfx; pub use export::gfx;
pub use export::gleam::gl; pub use export::gleam::gl;
pub use export::ipc_channel;
pub use export::layers; pub use export::layers;
pub use export::layout; pub use export::layout;
pub use export::msg; pub use export::msg;
@ -193,7 +200,7 @@ fn create_constellation(opts: opts::Opts,
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan, mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>, devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
supports_clipboard: bool) -> ConstellationChan<ConstellationMsg> { supports_clipboard: bool) -> Sender<ConstellationMsg> {
let resource_task = new_resource_task(opts.user_agent.clone(), devtools_chan.clone()); let resource_task = new_resource_task(opts.user_agent.clone(), devtools_chan.clone());
let image_cache_task = new_image_cache_task(resource_task.clone()); let image_cache_task = new_image_cache_task(resource_task.clone());
@ -218,11 +225,33 @@ fn create_constellation(opts: opts::Opts,
// Send the URL command to the constellation. // Send the URL command to the constellation.
match opts.url { match opts.url {
Some(url) => { Some(url) => {
let ConstellationChan(ref chan) = constellation_chan; constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
}, },
None => () None => ()
}; };
constellation_chan constellation_chan
} }
/// Content process entry point.
pub fn run_content_process(token: String) {
let (unprivileged_content_sender, unprivileged_content_receiver) =
ipc::channel::<UnprivilegedPipelineContent>().unwrap();
let connection_bootstrap: IpcSender<IpcSender<UnprivilegedPipelineContent>> =
IpcSender::connect(token).unwrap();
connection_bootstrap.send(unprivileged_content_sender).unwrap();
let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
opts::set_defaults(unprivileged_content.opts());
// Enter the sandbox if necessary.
if opts::get().sandbox {
ChildSandbox::new(sandboxing::content_process_sandbox_profile()).activate().unwrap();
}
script::init();
unprivileged_content.start_all::<layout::layout_task::LayoutTask,
script::script_task::ScriptTask>(true);
}

View file

@ -39,7 +39,7 @@ use offscreen_gl_context::GLContext;
use servo::Browser; use servo::Browser;
use servo::compositing::windowing::WindowEvent; use servo::compositing::windowing::WindowEvent;
use servo::net_traits::hosts; use servo::net_traits::hosts;
use servo::util::opts; use servo::util::opts::{self, ArgumentParsingResult};
use std::rc::Rc; use std::rc::Rc;
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
@ -52,11 +52,17 @@ fn load_gl_when_headless() {}
fn main() { fn main() {
// Parse the command line options and store them globally // Parse the command line options and store them globally
opts::from_cmdline_args(&*args()); let opts_result = opts::from_cmdline_args(&*args());
if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() { let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
::std::env::set_var("RUST_LOG", "compositing::constellation"); Some(token)
} } else {
if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
::std::env::set_var("RUST_LOG", "compositing::constellation");
}
None
};
env_logger::init().unwrap(); env_logger::init().unwrap();
@ -65,6 +71,10 @@ fn main() {
// Possibly interpret the `HOST_FILE` environment variable // Possibly interpret the `HOST_FILE` environment variable
hosts::global_init(); hosts::global_init();
if let Some(token) = content_process_token {
return servo::run_content_process(token)
}
let window = if opts::get().headless { let window = if opts::get().headless {
// Load gl functions even when in headless mode, // Load gl functions even when in headless mode,
// to avoid crashing with webgl // to avoid crashing with webgl

View file

@ -2,18 +2,20 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender, OpaqueIpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use opts; use opts;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::any::Any; use std::any::{Any, TypeId};
use std::collections::HashMap; use std::collections::HashMap;
use std::marker::Reflect;
use std::mem;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::sync::mpsc::{self, Receiver, Sender}; use std::sync::mpsc::{self, Receiver, Sender};
lazy_static! { lazy_static! {
static ref IN_PROCESS_SENDERS: Mutex<HashMap<usize, Box<Any + Send>>> = static ref IN_PROCESS_SENDERS: Mutex<HashMap<usize, OpaqueSender>> =
Mutex::new(HashMap::new()); Mutex::new(HashMap::new());
} }
@ -31,6 +33,17 @@ impl<T> OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
OptionalIpcSender::InProcess(ref sender) => sender.send(value).map_err(|_| ()), OptionalIpcSender::InProcess(ref sender) => sender.send(value).map_err(|_| ()),
} }
} }
pub fn to_opaque(self) -> OptionalOpaqueIpcSender {
match self {
OptionalIpcSender::OutOfProcess(ipc_sender) => {
OptionalOpaqueIpcSender::OutOfProcess(ipc_sender.to_opaque())
}
OptionalIpcSender::InProcess(sender) => {
OptionalOpaqueIpcSender::InProcess(OpaqueSender::new(sender))
}
}
}
} }
impl<T> Clone for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any { impl<T> Clone for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
@ -49,18 +62,13 @@ impl<T> Clone for OptionalIpcSender<T> where T: Deserialize + Serialize + Send +
impl<T> Deserialize for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any { impl<T> Deserialize for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
fn deserialize<D>(deserializer: &mut D) fn deserialize<D>(deserializer: &mut D)
-> Result<OptionalIpcSender<T>, D::Error> where D: Deserializer { -> Result<OptionalIpcSender<T>, D::Error> where D: Deserializer {
if opts::get().multiprocess { if opts::multiprocess() {
return Ok(OptionalIpcSender::OutOfProcess(try!(Deserialize::deserialize( return Ok(OptionalIpcSender::OutOfProcess(try!(Deserialize::deserialize(
deserializer)))) deserializer))))
} }
let id: usize = try!(Deserialize::deserialize(deserializer)); let id: usize = try!(Deserialize::deserialize(deserializer));
let sender = (*IN_PROCESS_SENDERS.lock() let sender = IN_PROCESS_SENDERS.lock().unwrap().remove(&id).unwrap();
.unwrap() Ok(OptionalIpcSender::InProcess(sender.to().unwrap()))
.remove(&id)
.unwrap()
.downcast_ref::<Sender<T>>()
.unwrap()).clone();
Ok(OptionalIpcSender::InProcess(sender))
} }
} }
@ -72,16 +80,91 @@ impl<T> Serialize for OptionalIpcSender<T> where T: Deserialize + Serialize + Se
let id = NEXT_SENDER_ID.fetch_add(1, Ordering::SeqCst); let id = NEXT_SENDER_ID.fetch_add(1, Ordering::SeqCst);
IN_PROCESS_SENDERS.lock() IN_PROCESS_SENDERS.lock()
.unwrap() .unwrap()
.insert(id, Box::new((*sender).clone()) as Box<Any + Send>); .insert(id, OpaqueSender::new((*sender).clone()));
id.serialize(serializer) id.serialize(serializer)
} }
} }
} }
} }
#[derive(Clone)]
pub enum OptionalOpaqueIpcSender {
OutOfProcess(OpaqueIpcSender),
InProcess(OpaqueSender),
}
impl OptionalOpaqueIpcSender {
pub fn to<T>(self) -> OptionalIpcSender<T>
where T: Deserialize + Serialize + Send + Any + 'static {
match self {
OptionalOpaqueIpcSender::OutOfProcess(ipc_sender) => {
OptionalIpcSender::OutOfProcess(ipc_sender.to())
}
OptionalOpaqueIpcSender::InProcess(sender) => {
OptionalIpcSender::InProcess(sender.to().unwrap())
}
}
}
}
impl Deserialize for OptionalOpaqueIpcSender {
fn deserialize<D>(deserializer: &mut D)
-> Result<OptionalOpaqueIpcSender, D::Error> where D: Deserializer {
if opts::multiprocess() {
return Ok(OptionalOpaqueIpcSender::OutOfProcess(try!(Deserialize::deserialize(
deserializer))))
}
let id: usize = try!(Deserialize::deserialize(deserializer));
let sender = IN_PROCESS_SENDERS.lock().unwrap().remove(&id).unwrap();
Ok(OptionalOpaqueIpcSender::InProcess(sender))
}
}
impl Serialize for OptionalOpaqueIpcSender {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
match *self {
OptionalOpaqueIpcSender::OutOfProcess(ref ipc_sender) => {
ipc_sender.serialize(serializer)
}
OptionalOpaqueIpcSender::InProcess(ref sender) => {
let id = NEXT_SENDER_ID.fetch_add(1, Ordering::SeqCst);
IN_PROCESS_SENDERS.lock().unwrap().insert(id, (*sender).clone());
id.serialize(serializer)
}
}
}
}
#[derive(Clone)]
pub struct OpaqueSender {
sender: Sender<()>,
id: TypeId,
}
impl OpaqueSender {
fn new<T>(sender: Sender<T>) -> OpaqueSender where T: 'static + Reflect + Send {
unsafe {
OpaqueSender {
sender: mem::transmute::<_, Sender<()>>(sender),
id: TypeId::of::<T>(),
}
}
}
fn to<T>(self) -> Option<Sender<T>> where T: 'static + Reflect + Send {
unsafe {
if self.id != TypeId::of::<T>() {
None
} else {
Some(mem::transmute::<_, Sender<T>>(self.sender))
}
}
}
}
pub fn optional_ipc_channel<T>() -> (OptionalIpcSender<T>, Receiver<T>) pub fn optional_ipc_channel<T>() -> (OptionalIpcSender<T>, Receiver<T>)
where T: Deserialize + Serialize + Send + Any { where T: Deserialize + Serialize + Send + Any {
if opts::get().multiprocess { if opts::multiprocess() {
let (ipc_sender, ipc_receiver) = ipc::channel().unwrap(); let (ipc_sender, ipc_receiver) = ipc::channel().unwrap();
let receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_receiver); let receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_receiver);
(OptionalIpcSender::OutOfProcess(ipc_sender), receiver) (OptionalIpcSender::OutOfProcess(ipc_sender), receiver)

View file

@ -14,6 +14,7 @@
#![feature(optin_builtin_traits)] #![feature(optin_builtin_traits)]
#![cfg_attr(not(target_os = "android"), feature(path_ext))] #![cfg_attr(not(target_os = "android"), feature(path_ext))]
#![feature(plugin)] #![feature(plugin)]
#![feature(reflect_marker)]
#![feature(slice_splits)] #![feature(slice_splits)]
#![feature(step_by)] #![feature(step_by)]
#![feature(step_trait)] #![feature(step_trait)]

View file

@ -18,10 +18,11 @@ use std::fs::File;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::path::Path; use std::path::Path;
use std::process; use std::process;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use url::{self, Url}; use url::{self, Url};
/// Global flags for Servo, currently set on the command line. /// Global flags for Servo, currently set on the command line.
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub struct Opts { pub struct Opts {
pub is_running_problem_test: bool, pub is_running_problem_test: bool,
@ -143,9 +144,12 @@ pub struct Opts {
/// An optional string allowing the user agent to be set for testing. /// An optional string allowing the user agent to be set for testing.
pub user_agent: String, pub user_agent: String,
/// Whether to run in multiprocess mode. /// Whether we're running in multiprocess mode.
pub multiprocess: bool, pub multiprocess: bool,
/// Whether we're running inside the sandbox.
pub sandbox: bool,
/// Dumps the flow tree after a layout. /// Dumps the flow tree after a layout.
pub dump_flow_tree: bool, pub dump_flow_tree: bool,
@ -375,6 +379,13 @@ static FORCE_CPU_PAINTING: bool = true;
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
static FORCE_CPU_PAINTING: bool = false; static FORCE_CPU_PAINTING: bool = false;
static MULTIPROCESS: AtomicBool = ATOMIC_BOOL_INIT;
#[inline]
pub fn multiprocess() -> bool {
MULTIPROCESS.load(Ordering::Relaxed)
}
enum UserAgent { enum UserAgent {
Desktop, Desktop,
Android, Android,
@ -460,6 +471,7 @@ pub fn default_opts() -> Opts {
initial_window_size: Size2D::typed(800, 600), initial_window_size: Size2D::typed(800, 600),
user_agent: default_user_agent_string(DEFAULT_USER_AGENT), user_agent: default_user_agent_string(DEFAULT_USER_AGENT),
multiprocess: false, multiprocess: false,
sandbox: false,
dump_flow_tree: false, dump_flow_tree: false,
dump_display_list: false, dump_display_list: false,
dump_display_list_json: false, dump_display_list_json: false,
@ -479,7 +491,7 @@ pub fn default_opts() -> Opts {
} }
} }
pub fn from_cmdline_args(args: &[String]) { pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
let (app_name, args) = args.split_first().unwrap(); let (app_name, args) = args.split_first().unwrap();
let mut opts = Options::new(); let mut opts = Options::new();
@ -509,11 +521,14 @@ pub fn from_cmdline_args(args: &[String]) {
"Set custom user agent string (or android / gonk / desktop for platform default)", "Set custom user agent string (or android / gonk / desktop for platform default)",
"NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"); "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)");
opts.optflag("M", "multiprocess", "Run in multiprocess mode"); opts.optflag("M", "multiprocess", "Run in multiprocess mode");
opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess");
opts.optopt("Z", "debug", opts.optopt("Z", "debug",
"A comma-separated string of debug options. Pass help to show available options.", ""); "A comma-separated string of debug options. Pass help to show available options.", "");
opts.optflag("h", "help", "Print this message"); opts.optflag("h", "help", "Print this message");
opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources"); opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources");
opts.optflag("", "sniff-mime-types" , "Enable MIME sniffing"); opts.optflag("", "sniff-mime-types" , "Enable MIME sniffing");
opts.optopt("", "content-process" , "Run as a content process and connect to the given pipe",
"servo-ipc-channel.abcdefg");
opts.optmulti("", "pref", opts.optmulti("", "pref",
"A preference to set to enable", "dom.mozbrowser.enabled"); "A preference to set to enable", "dom.mozbrowser.enabled");
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
@ -530,6 +545,13 @@ pub fn from_cmdline_args(args: &[String]) {
process::exit(0); process::exit(0);
}; };
// If this is the content process, we'll receive the real options over IPC. So just fill in
// some dummy options for now.
if let Some(content_process) = opt_match.opt_str("content-process") {
MULTIPROCESS.store(true, Ordering::SeqCst);
return ArgumentParsingResult::ContentProcess(content_process);
}
let debug_string = match opt_match.opt_str("Z") { let debug_string = match opt_match.opt_str("Z") {
Some(string) => string, Some(string) => string,
None => String::new() None => String::new()
@ -627,6 +649,10 @@ pub fn from_cmdline_args(args: &[String]) {
} }
}; };
if opt_match.opt_present("M") {
MULTIPROCESS.store(true, Ordering::SeqCst)
}
let user_agent = match opt_match.opt_str("u") { let user_agent = match opt_match.opt_str("u") {
Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android), Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android),
Some(ref ua) if ua == "gonk" => default_user_agent_string(UserAgent::Gonk), Some(ref ua) if ua == "gonk" => default_user_agent_string(UserAgent::Gonk),
@ -675,6 +701,7 @@ pub fn from_cmdline_args(args: &[String]) {
initial_window_size: initial_window_size, initial_window_size: initial_window_size,
user_agent: user_agent, user_agent: user_agent,
multiprocess: opt_match.opt_present("M"), multiprocess: opt_match.opt_present("M"),
sandbox: opt_match.opt_present("S"),
show_debug_borders: debug_options.show_compositor_borders, show_debug_borders: debug_options.show_compositor_borders,
show_debug_fragment_borders: debug_options.show_fragment_borders, show_debug_fragment_borders: debug_options.show_fragment_borders,
show_debug_parallel_paint: debug_options.show_parallel_paint, show_debug_parallel_paint: debug_options.show_parallel_paint,
@ -704,6 +731,22 @@ pub fn from_cmdline_args(args: &[String]) {
for pref in opt_match.opt_strs("pref").iter() { for pref in opt_match.opt_strs("pref").iter() {
prefs::set_pref(pref, PrefValue::Boolean(true)); prefs::set_pref(pref, PrefValue::Boolean(true));
} }
ArgumentParsingResult::ChromeProcess
}
pub enum ArgumentParsingResult {
ChromeProcess,
ContentProcess(String),
}
static EXPERIMENTAL_ENABLED: AtomicBool = ATOMIC_BOOL_INIT;
/// Turn on experimental features globally. Normally this is done
/// during initialization by `set` or `from_cmdline_args`, but
/// tests that require experimental features will also set it.
pub fn set_experimental_enabled(new_value: bool) {
EXPERIMENTAL_ENABLED.store(new_value, Ordering::SeqCst);
} }
// Make Opts available globally. This saves having to clone and pass // Make Opts available globally. This saves having to clone and pass

View file

@ -558,7 +558,7 @@ pub fn parse_legacy_color(mut input: &str) -> Result<RGBA, ()> {
} }
#[derive(Clone, Eq, PartialEq, Hash, Debug)] #[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize)]
pub struct LowercaseString { pub struct LowercaseString {
inner: String, inner: String,
} }

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ipc_channel::ipc::IpcSender;
use serde::Serialize;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::thread; use std::thread;
@ -15,15 +17,36 @@ pub fn spawn_named<F>(name: String, f: F)
builder.spawn(f).unwrap(); builder.spawn(f).unwrap();
} }
/// An abstraction over `Sender<T>` and `IpcSender<T>`, for use in
/// `spawn_named_with_send_on_failure`.
pub trait SendOnFailure {
type Value;
fn send_on_failure(&mut self, value: Self::Value);
}
impl<T> SendOnFailure for Sender<T> where T: Send + 'static {
type Value = T;
fn send_on_failure(&mut self, value: T) {
self.send(value).unwrap();
}
}
impl<T> SendOnFailure for IpcSender<T> where T: Send + Serialize + 'static {
type Value = T;
fn send_on_failure(&mut self, value: T) {
self.send(value).unwrap();
}
}
/// Arrange to send a particular message to a channel if the task fails. /// Arrange to send a particular message to a channel if the task fails.
pub fn spawn_named_with_send_on_failure<F, T>(name: String, pub fn spawn_named_with_send_on_failure<F, T, S>(name: String,
state: task_state::TaskState, state: task_state::TaskState,
f: F, f: F,
msg: T, msg: T,
dest: Sender<T>) mut dest: S)
where F: FnOnce() + Send + 'static, where F: FnOnce() + Send + 'static,
T: Send + 'static T: Send + 'static,
{ S: Send + SendOnFailure<Value=T> + 'static {
let future_handle = thread::Builder::new().name(name.to_owned()).spawn(move || { let future_handle = thread::Builder::new().name(name.to_owned()).spawn(move || {
task_state::initialize(state); task_state::initialize(state);
f() f()
@ -35,8 +58,9 @@ pub fn spawn_named_with_send_on_failure<F, T>(name: String,
Ok(()) => (), Ok(()) => (),
Err(..) => { Err(..) => {
debug!("{} failed, notifying constellation", name); debug!("{} failed, notifying constellation", name);
dest.send(msg).unwrap(); dest.send_on_failure(msg);
} }
} }
}).unwrap(); }).unwrap();
} }

View file

@ -28,7 +28,7 @@ use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use keys::keycodes_to_keys; use keys::keycodes_to_keys;
use msg::constellation_msg::CompositorMsg as ConstellationMsg; use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, FrameId, LoadData, PipelineId}; use msg::constellation_msg::{FrameId, LoadData, PipelineId};
use msg::constellation_msg::{NavigationDirection, PixelFormat, WebDriverCommandMsg}; use msg::constellation_msg::{NavigationDirection, PixelFormat, WebDriverCommandMsg};
use msg::webdriver_msg::{LoadStatus, WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverScriptCommand}; use msg::webdriver_msg::{LoadStatus, WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverScriptCommand};
use regex::Captures; use regex::Captures;
@ -37,6 +37,7 @@ use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::mpsc::Sender;
use std::thread::{self, sleep_ms}; use std::thread::{self, sleep_ms};
use url::Url; use url::Url;
use util::prefs::{get_pref, reset_all_prefs, reset_pref, set_pref, PrefValue}; use util::prefs::{get_pref, reset_all_prefs, reset_pref, set_pref, PrefValue};
@ -57,7 +58,7 @@ fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> {
(Post, "/session/{sessionId}/servo/prefs/reset", ServoExtensionRoute::ResetPrefs)] (Post, "/session/{sessionId}/servo/prefs/reset", ServoExtensionRoute::ResetPrefs)]
} }
pub fn start_server(port: u16, constellation_chan: ConstellationChan<ConstellationMsg>) { pub fn start_server(port: u16, constellation_chan: Sender<ConstellationMsg>) {
let handler = Handler::new(constellation_chan); let handler = Handler::new(constellation_chan);
spawn_named("WebdriverHttpServer".to_owned(), move || { spawn_named("WebdriverHttpServer".to_owned(), move || {
server::start(SocketAddr::new("0.0.0.0".parse().unwrap(), port), handler, server::start(SocketAddr::new("0.0.0.0".parse().unwrap(), port), handler,
@ -72,7 +73,7 @@ struct WebDriverSession {
struct Handler { struct Handler {
session: Option<WebDriverSession>, session: Option<WebDriverSession>,
constellation_chan: ConstellationChan<ConstellationMsg>, constellation_chan: Sender<ConstellationMsg>,
script_timeout: u32, script_timeout: u32,
load_timeout: u32, load_timeout: u32,
implicit_wait_timeout: u32 implicit_wait_timeout: u32
@ -208,7 +209,7 @@ impl WebDriverSession {
} }
impl Handler { impl Handler {
pub fn new(constellation_chan: ConstellationChan<ConstellationMsg>) -> Handler { pub fn new(constellation_chan: Sender<ConstellationMsg>) -> Handler {
Handler { Handler {
session: None, session: None,
constellation_chan: constellation_chan, constellation_chan: constellation_chan,
@ -267,8 +268,7 @@ impl Handler {
fn pipeline(&self, frame_id: Option<FrameId>) -> Option<PipelineId> { fn pipeline(&self, frame_id: Option<FrameId>) -> Option<PipelineId> {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap();
const_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap();
receiver.recv().unwrap() receiver.recv().unwrap()
@ -307,9 +307,8 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let load_data = LoadData::new(url); let load_data = LoadData::new(url);
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone()); let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone());
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.wait_for_load(sender, receiver) self.wait_for_load(sender, receiver)
} }
@ -337,10 +336,9 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
WebDriverScriptCommand::GetUrl(sender)); WebDriverScriptCommand::GetUrl(sender));
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
let url = receiver.recv().unwrap(); let url = receiver.recv().unwrap();
@ -348,14 +346,12 @@ impl Handler {
} }
fn handle_go_back(&self) -> WebDriverResult<WebDriverResponse> { fn handle_go_back(&self) -> WebDriverResult<WebDriverResponse> {
let ConstellationChan(ref const_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap();
const_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap();
Ok(WebDriverResponse::Void) Ok(WebDriverResponse::Void)
} }
fn handle_go_forward(&self) -> WebDriverResult<WebDriverResponse> { fn handle_go_forward(&self) -> WebDriverResult<WebDriverResponse> {
let ConstellationChan(ref const_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Forward)).unwrap();
const_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Forward)).unwrap();
Ok(WebDriverResponse::Void) Ok(WebDriverResponse::Void)
} }
@ -364,9 +360,8 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::Refresh(pipeline_id, sender.clone()); let cmd_msg = WebDriverCommandMsg::Refresh(pipeline_id, sender.clone());
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.wait_for_load(sender, receiver) self.wait_for_load(sender, receiver)
} }
@ -375,10 +370,9 @@ impl Handler {
let pipeline_id = try!(self.root_pipeline()); let pipeline_id = try!(self.root_pipeline());
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
WebDriverScriptCommand::GetTitle(sender)); WebDriverScriptCommand::GetTitle(sender));
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
let value = receiver.recv().unwrap(); let value = receiver.recv().unwrap();
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))) Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
} }
@ -406,10 +400,9 @@ impl Handler {
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender); let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => { Ok(value) => {
let value_resp = value.map(|x| WebElement::new(x).to_json()).to_json(); let value_resp = value.map(|x| WebElement::new(x).to_json()).to_json();
@ -448,16 +441,14 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::GetFrameId(frame_id, sender); let cmd = WebDriverScriptCommand::GetFrameId(frame_id, sender);
{ {
let ConstellationChan(ref const_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::WebDriverCommand(
const_chan.send(ConstellationMsg::WebDriverCommand(
WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap(); WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap();
} }
let frame = match receiver.recv().unwrap() { let frame = match receiver.recv().unwrap() {
Ok(Some(pipeline_id)) => { Ok(Some(pipeline_id)) => {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan; self.constellation_chan.send(ConstellationMsg::GetFrame(pipeline_id, sender)).unwrap();
const_chan.send(ConstellationMsg::GetFrame(pipeline_id, sender)).unwrap();
receiver.recv().unwrap() receiver.recv().unwrap()
}, },
Ok(None) => None, Ok(None) => None,
@ -481,10 +472,9 @@ impl Handler {
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender); let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => { Ok(value) => {
let resp_value: Vec<Json> = value.into_iter().map( let resp_value: Vec<Json> = value.into_iter().map(
@ -500,10 +490,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender); let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -515,10 +504,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetActiveElement(sender); let cmd = WebDriverScriptCommand::GetActiveElement(sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
let value = receiver.recv().unwrap().map(|x| WebElement::new(x).to_json()); let value = receiver.recv().unwrap().map(|x| WebElement::new(x).to_json());
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))) Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
} }
@ -527,10 +515,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender); let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -542,10 +529,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetElementAttribute(element.id.clone(), name.clone(), sender); let cmd = WebDriverScriptCommand::GetElementAttribute(element.id.clone(), name.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -601,9 +587,8 @@ impl Handler {
-> WebDriverResult<WebDriverResponse> { -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, command); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, command);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))), Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
@ -618,12 +603,11 @@ impl Handler {
keys: &SendKeysParameters) -> WebDriverResult<WebDriverResponse> { keys: &SendKeysParameters) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.frame_pipeline()); let pipeline_id = try!(self.frame_pipeline());
let ConstellationChan(ref const_chan) = self.constellation_chan;
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::FocusElement(element.id.clone(), sender); let cmd = WebDriverScriptCommand::FocusElement(element.id.clone(), sender);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
// TODO: distinguish the not found and not focusable cases // TODO: distinguish the not found and not focusable cases
try!(receiver.recv().unwrap().or_else(|_| Err(WebDriverError::new( try!(receiver.recv().unwrap().or_else(|_| Err(WebDriverError::new(
@ -633,7 +617,7 @@ impl Handler {
Err(WebDriverError::new(ErrorStatus::UnsupportedOperation, "Failed to convert keycodes")))); Err(WebDriverError::new(ErrorStatus::UnsupportedOperation, "Failed to convert keycodes"))));
let cmd_msg = WebDriverCommandMsg::SendKeys(pipeline_id, keys); let cmd_msg = WebDriverCommandMsg::SendKeys(pipeline_id, keys);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
Ok(WebDriverResponse::Void) Ok(WebDriverResponse::Void)
} }
@ -647,9 +631,8 @@ impl Handler {
for _ in 0..iterations { for _ in 0..iterations {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::TakeScreenshot(pipeline_id, sender); let cmd_msg = WebDriverCommandMsg::TakeScreenshot(pipeline_id, sender);
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
if let Some(x) = receiver.recv().unwrap() { if let Some(x) = receiver.recv().unwrap() {
img = Some(x); img = Some(x);

16
ports/cef/Cargo.lock generated
View file

@ -253,6 +253,7 @@ dependencies = [
"core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@ -260,6 +261,7 @@ dependencies = [
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout_traits 0.0.1", "layout_traits 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1", "msg 0.0.1",
"net_traits 0.0.1", "net_traits 0.0.1",
@ -268,6 +270,8 @@ dependencies = [
"plugins 0.0.1", "plugins 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1", "style_traits 0.0.1",
"time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
@ -559,6 +563,16 @@ dependencies = [
"mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "gaol"
version = "0.0.1"
source = "git+https://github.com/pcwalton/gaol#71865ff8a1824cbc1cbee4d388d56c5ba1b5ffc2"
dependencies = [
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.16" version = "0.3.16"
@ -1555,9 +1569,11 @@ dependencies = [
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin_app 0.0.1", "glutin_app 0.0.1",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout 0.0.1", "layout 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",

16
ports/gonk/Cargo.lock generated
View file

@ -245,6 +245,7 @@ dependencies = [
"core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@ -252,6 +253,7 @@ dependencies = [
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout_traits 0.0.1", "layout_traits 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1", "msg 0.0.1",
"net_traits 0.0.1", "net_traits 0.0.1",
@ -260,6 +262,8 @@ dependencies = [
"plugins 0.0.1", "plugins 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1", "style_traits 0.0.1",
"time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
@ -561,6 +565,16 @@ dependencies = [
"mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "gaol"
version = "0.0.1"
source = "git+https://github.com/pcwalton/gaol#71865ff8a1824cbc1cbee4d388d56c5ba1b5ffc2"
dependencies = [
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.16" version = "0.3.16"
@ -1535,8 +1549,10 @@ dependencies = [
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout 0.0.1", "layout 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",