servo: Merge #8599 - compositing: Split Servo up into multiple sandboxed processes (from jdm:e10s-redux); r=metajack

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

Rebase of #6884.

Source-Repo: https://github.com/servo/servo
Source-Revision: 8b39b9afed6ef8a3d7d3e6609fd301a37825d3e1
This commit is contained in:
Patrick Walton 2015-11-20 03:30:48 +05:01
Родитель a4e688b2a0
Коммит 8c7de61738
33 изменённых файлов: 688 добавлений и 265 удалений

Просмотреть файл

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

Просмотреть файл

@ -17,7 +17,7 @@ use gfx_traits::color;
use gleam::gl;
use gleam::gl::types::{GLint, GLsizei};
use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory};
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use ipc_channel::router::ROUTER;
use layers::geometry::{DevicePixel, LayerPixel};
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::constellation_msg::CompositorMsg as ConstellationMsg;
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 pipeline::CompositionPipeline;
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
@ -168,7 +168,7 @@ pub struct IOCompositor<Window: WindowMethods> {
frame_tree_id: FrameTreeId,
/// 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.
time_profiler_chan: time::ProfilerChan,
@ -385,8 +385,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
pub fn start_shutting_down(&mut self) {
debug!("Compositor sending Exit message to Constellation");
let ConstellationChan(ref constellation_channel) = self.constellation_chan;
constellation_channel.send(ConstellationMsg::Exit).unwrap();
self.constellation_chan.send(ConstellationMsg::Exit).unwrap();
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,
frame_tree: &SendableFrameTree,
response_chan: Sender<()>,
new_constellation_chan: ConstellationChan<ConstellationMsg>) {
response_chan: IpcSender<()>,
new_constellation_chan: Sender<ConstellationMsg>) {
response_chan.send(()).unwrap();
// 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 visible_viewport = initial_viewport / self.viewport_zoom;
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
self.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
device_pixel_ratio: dppx,
initial_viewport: initial_viewport,
visible_viewport: visible_viewport,
@ -959,9 +957,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
None => return,
};
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::FrameSize(*subpage_pipeline_id,
layer_properties.rect.size)).unwrap();
self.constellation_chan.send(ConstellationMsg::FrameSize(
*subpage_pipeline_id,
layer_properties.rect.size)).unwrap();
}
pub fn move_layer(&self,
@ -1168,8 +1166,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
None => ConstellationMsg::InitLoadUrl(url)
};
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(msg).unwrap()
self.constellation_chan.send(msg).unwrap()
}
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) {
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) {
@ -1538,13 +1535,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
windowing::WindowNavigateMsg::Forward => NavigationDirection::Forward,
windowing::WindowNavigateMsg::Back => NavigationDirection::Back,
};
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::Navigate(None, direction)).unwrap()
self.constellation_chan.send(ConstellationMsg::Navigate(None, direction)).unwrap()
}
fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) {
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
self.constellation_chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
}
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
// if it's safe to output the image.
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::IsReadyToSaveImage(pipeline_epochs)).unwrap();
self.constellation_chan.send(ConstellationMsg::IsReadyToSaveImage(pipeline_epochs)).unwrap();
self.ready_to_save_state = ReadyState::WaitingForConstellationReply;
Err(NotReadyToPaint::JustNotifiedConstellation)
}
@ -2167,8 +2161,7 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind
None => return,
Some(ref root_pipeline) => root_pipeline.id,
};
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id)).unwrap();
self.constellation_chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id)).unwrap();
}
}

Просмотреть файл

@ -5,15 +5,16 @@
//! Communication with the compositor task.
use compositor;
use euclid::{Point2D, Size2D};
use euclid::point::Point2D;
use euclid::size::Size2D;
use headless;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use layers::layers::{BufferRequest, LayerBufferSet};
use layers::platform::surface::{NativeDisplay, NativeSurface};
use msg::compositor_msg::{Epoch, EventResult, FrameTreeId, LayerId, LayerProperties};
use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
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 profile_traits::mem;
use profile_traits::time;
@ -60,11 +61,11 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
receiver: IpcReceiver<ScriptToCompositorMsg>) {
while let Ok(msg) = receiver.recv() {
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,
layer_id,
point,
_smooth));
smooth));
}
ScriptToCompositorMsg::GetClientWindow(send) => {
@ -80,7 +81,7 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
}
ScriptToCompositorMsg::Exit => {
let (chan, port) = channel();
let (chan, port) = ipc::channel().unwrap();
compositor_proxy.send(Msg::Exit(chan));
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.
pub enum Msg {
/// Requests that the compositor shut down.
Exit(Sender<()>),
Exit(IpcSender<()>),
/// Informs the compositor that the constellation has completed shutdown.
/// 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.
ChangeRunningAnimationsState(PipelineId, AnimationState),
/// 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).
LoadStart(bool, bool),
/// 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.
pub receiver: Box<CompositorReceiver>,
/// A channel to the constellation.
pub constellation_chan: ConstellationChan<ConstellationMsg>,
pub constellation_chan: Sender<ConstellationMsg>,
/// A channel to the time profiler thread.
pub time_profiler_chan: time::ProfilerChan,
/// A channel to the memory profiler thread.

Просмотреть файл

@ -18,8 +18,11 @@ use compositor_task::Msg as ToCompositorMsg;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
use gaol;
use gaol::sandbox::{self, Sandbox, SandboxMethods};
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 msg::compositor_msg::Epoch;
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::{self, ResourceTask};
use offscreen_gl_context::GLContextAttributes;
use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline};
use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline, UnprivilegedPipelineContent};
use profile_traits::mem;
use profile_traits::time;
use sandboxing;
use script_traits::{CompositorEvent, ConstellationControlMsg, LayoutControlMsg};
use script_traits::{ScriptState, ScriptTaskFactory};
use script_traits::{TimerEventRequest};
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::env;
use std::io::{self, Write};
use std::marker::PhantomData;
use std::mem::replace;
use std::process;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::sync::mpsc::{Sender, channel, Receiver};
use style_traits::viewport::ViewportConstraints;
use timer_scheduler::TimerScheduler;
use url::Url;
@ -79,7 +84,7 @@ pub struct Constellation<LTF, STF> {
pub script_sender: ConstellationChan<FromScriptMsg>,
/// 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.
pub script_receiver: Receiver<FromScriptMsg>,
@ -156,6 +161,9 @@ pub struct Constellation<LTF, STF> {
webgl_paint_tasks: Vec<Sender<CanvasMsg>>,
scheduler_chan: IpcSender<TimerEventRequest>,
/// A list of child content processes.
child_processes: Vec<ChildProcess>,
}
/// State needed to construct a constellation.
@ -259,14 +267,21 @@ enum ExitPipelineMode {
Force,
}
enum ChildProcess {
Sandboxed(gaol::platform::process::Process),
Unsandboxed(process::Child),
}
impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pub fn start(state: InitialConstellationState) -> ConstellationChan<FromCompositorMsg> {
let (script_receiver, script_sender) = ConstellationChan::<FromScriptMsg>::new();
let (compositor_receiver, compositor_sender) = ConstellationChan::<FromCompositorMsg>::new();
pub fn start(state: InitialConstellationState) -> Sender<FromCompositorMsg> {
let (ipc_script_receiver, ipc_script_sender) = ConstellationChan::<FromScriptMsg>::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();
spawn_named("Constellation".to_owned(), move || {
let mut constellation: Constellation<LTF, STF> = Constellation {
script_sender: script_sender,
script_sender: ipc_script_sender,
compositor_sender: compositor_sender_clone,
script_receiver: script_receiver,
compositor_receiver: compositor_receiver,
@ -305,6 +320,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
canvas_paint_tasks: Vec::new(),
webgl_paint_tasks: Vec::new(),
scheduler_chan: TimerScheduler::start(),
child_processes: Vec::new(),
};
let namespace_id = constellation.next_pipeline_namespace_id();
PipelineNamespace::install(namespace_id);
@ -333,10 +349,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pipeline_id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>,
initial_window_size: Option<TypedSize2D<PagePx, f32>>,
script_channel: Option<Sender<ConstellationControlMsg>>,
script_channel: Option<IpcSender<ConstellationControlMsg>>,
load_data: LoadData) {
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 {
id: pipeline_id,
parent_info: parent_info,
@ -357,12 +373,39 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
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 {
pipeline_content.start_paint_task();
privileged_pipeline_content.start_paint_task();
} 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));
@ -1290,7 +1333,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
// Synchronously query the script task for this pipeline
// to see if it is idle.
let (sender, receiver) = channel();
let (sender, receiver) = ipc::channel().unwrap();
let msg = ConstellationControlMsg::GetCurrentState(sender, frame.current);
pipeline.script_chan.send(msg).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 {
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,
chan,
self.compositor_sender.clone()));

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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!")
}

Просмотреть файл

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

Просмотреть файл

@ -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.
///
/// 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 weight: font_weight::T,
pub stretch: font_stretch::T,

Просмотреть файл

@ -36,8 +36,7 @@ use std::sync::mpsc::{Receiver, Select, Sender, channel};
use url::Url;
use util::geometry::{ExpandToPixelBoundaries, ZERO_POINT};
use util::opts;
use util::task::spawn_named;
use util::task::spawn_named_with_send_on_failure;
use util::task;
use util::task_state;
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
@ -255,9 +254,11 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
failure_msg: Failure,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: Sender<()>) {
shutdown_chan: IpcSender<()>) {
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
// shutdown message.
@ -572,7 +573,7 @@ impl WorkerThreadProxy {
let (to_worker_sender, to_worker_receiver) = channel();
let font_cache_task = font_cache_task.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,
to_worker_receiver,
native_display,

Просмотреть файл

@ -70,7 +70,7 @@ use util::ipc::OptionalIpcSender;
use util::logical_geometry::LogicalPoint;
use util::mem::HeapSizeOf;
use util::opts;
use util::task::spawn_named_with_send_on_failure;
use util::task;
use util::task_state;
use util::workqueue::WorkQueue;
use wrapper::{LayoutDocument, LayoutElement, LayoutNode, ServoLayoutNode};
@ -137,13 +137,13 @@ pub struct LayoutTask {
font_cache_receiver: Receiver<()>,
/// 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.
constellation_chan: ConstellationChan<ConstellationMsg>,
/// 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.
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
@ -219,17 +219,18 @@ impl LayoutTaskFactory for LayoutTask {
pipeline_port: IpcReceiver<LayoutControlMsg>,
constellation_chan: ConstellationChan<ConstellationMsg>,
failure_msg: Failure,
script_chan: Sender<ConstellationControlMsg>,
script_chan: IpcSender<ConstellationControlMsg>,
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: Sender<()>) {
shutdown_chan: IpcSender<()>,
content_process_shutdown_chan: IpcSender<()>) {
let ConstellationChan(con_chan) = constellation_chan.clone();
spawn_named_with_send_on_failure(format!("LayoutTask {:?}", id),
task_state::LAYOUT,
move || {
task::spawn_named_with_send_on_failure(format!("LayoutTask {:?}", id),
task_state::LAYOUT,
move || {
{ // Ensures layout task is destroyed before we send shutdown message
let sender = chan.sender();
let layout = LayoutTask::new(id,
@ -250,7 +251,8 @@ impl LayoutTaskFactory for LayoutTask {
layout.start();
}, 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);
}
}
@ -318,12 +320,12 @@ impl<'a, 'b: 'a> RwData<'a, 'b> {
fn add_font_face_rules(stylesheet: &Stylesheet,
device: &Device,
font_cache_task: &FontCacheTask,
font_cache_sender: &Sender<()>,
font_cache_sender: &IpcSender<()>,
outstanding_web_fonts_counter: &Arc<AtomicUsize>) {
for font_face in stylesheet.effective_rules(&device).font_face() {
for source in &font_face.sources {
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(),
(*source).clone(),
sender);
@ -346,7 +348,7 @@ impl LayoutTask {
port: Receiver<Msg>,
pipeline_port: IpcReceiver<LayoutControlMsg>,
constellation_chan: ConstellationChan<ConstellationMsg>,
script_chan: Sender<ConstellationControlMsg>,
script_chan: IpcSender<ConstellationControlMsg>,
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
@ -375,7 +377,10 @@ impl LayoutTask {
let 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 outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0));
@ -383,7 +388,7 @@ impl LayoutTask {
add_font_face_rules(stylesheet,
&stylist.device,
&font_cache_task,
&font_cache_sender,
&ipc_font_cache_sender,
&outstanding_web_fonts_counter);
}
@ -404,7 +409,7 @@ impl LayoutTask {
image_cache_receiver: image_cache_receiver,
image_cache_sender: ImageCacheChan(ipc_image_cache_sender),
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_sender: canvas_layers_sender,
parallel_traversal: parallel_traversal,
@ -668,14 +673,13 @@ impl LayoutTask {
info.constellation_chan,
info.failure,
info.script_chan.clone(),
*info.paint_chan
.downcast::<OptionalIpcSender<LayoutToPaintMsg>>()
.unwrap(),
info.paint_chan.to::<LayoutToPaintMsg>(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.time_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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -104,7 +104,7 @@ use time::{Tm, now};
use url::{Url, UrlParser};
use util::opts;
use util::str::DOMString;
use util::task::spawn_named_with_send_on_failure;
use util::task;
use util::task_state;
use webdriver_handlers;
@ -232,8 +232,9 @@ pub enum ScriptTaskEventCategory {
Resize,
ScriptEvent,
TimerEvent,
UpdateReplacedElement,
SetViewport,
StylesheetLoad,
UpdateReplacedElement,
WebSocketEvent,
WorkerEvent,
}
@ -396,7 +397,7 @@ pub struct ScriptTask {
chan: MainThreadScriptChan,
/// 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
/// script task.
@ -438,6 +439,8 @@ pub struct ScriptTask {
scheduler_chan: IpcSender<TimerEventRequest>,
timer_event_chan: Sender<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
@ -484,7 +487,8 @@ impl ScriptTaskFactory for ScriptTask {
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>
}
@ -496,9 +500,10 @@ impl ScriptTaskFactory for ScriptTask {
let (script_chan, script_port) = channel();
let layout_chan = LayoutChan(layout_chan.sender());
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);
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
let chan = MainThreadScriptChan(script_chan);
@ -524,6 +529,7 @@ impl ScriptTaskFactory for ScriptTask {
let reporter_name = format!("script-reporter-{}", id);
mem_profiler_chan.run_with_memory_reporting(|| {
script_task.start();
let _ = script_task.content_process_shutdown_chan.send(());
}, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports);
// 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();
// 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 {
page: DOMRefCell::new(None),
incomplete_loads: DOMRefCell::new(vec!()),
@ -650,7 +659,7 @@ impl ScriptTask {
port: port,
chan: chan,
control_chan: state.control_chan,
control_port: state.control_port,
control_port: control_port,
constellation_chan: state.constellation_chan,
compositor: DOMRefCell::new(state.compositor),
time_profiler_chan: state.time_profiler_chan,
@ -667,6 +676,8 @@ impl ScriptTask {
scheduler_chan: state.scheduler_chan,
timer_event_chan: timer_event_chan,
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::Resize => ProfilerCategory::ScriptResize,
ScriptTaskEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
ScriptTaskEventCategory::UpdateReplacedElement => ProfilerCategory::ScriptUpdateReplacedElement,
ScriptTaskEventCategory::UpdateReplacedElement => {
ProfilerCategory::ScriptUpdateReplacedElement
}
ScriptTaskEventCategory::StylesheetLoad => ProfilerCategory::ScriptStylesheetLoad,
ScriptTaskEventCategory::SetViewport => ProfilerCategory::ScriptSetViewport,
ScriptTaskEventCategory::TimerEvent => ProfilerCategory::ScriptTimerEvent,
ScriptTaskEventCategory::WebSocketEvent => ProfilerCategory::ScriptWebSocketEvent,
@ -1185,6 +1199,7 @@ impl ScriptTask {
failure,
pipeline_port,
layout_shutdown_chan,
content_process_shutdown_chan,
} = new_layout_info;
let layout_pair = ScriptTask::create_layout_channel(None::<&mut ScriptTask>);
@ -1204,6 +1219,7 @@ impl ScriptTask {
script_chan: self.control_chan.clone(),
image_cache_task: self.image_cache_task.clone(),
layout_shutdown_chan: layout_shutdown_chan,
content_process_shutdown_chan: content_process_shutdown_chan,
};
let page = self.root_page();

Просмотреть файл

@ -41,7 +41,7 @@ use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::StorageTask;
use profile_traits::mem;
use std::any::Any;
use std::sync::mpsc::{Receiver, Sender};
use util::ipc::OptionalOpaqueIpcSender;
use util::mem::HeapSizeOf;
/// 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.
#[derive(Deserialize, Serialize)]
pub struct NewLayoutInfo {
/// Id of the parent of this new pipeline.
pub containing_pipeline_id: PipelineId,
@ -77,21 +78,21 @@ pub struct NewLayoutInfo {
pub subpage_id: SubpageId,
/// Network request data which will be initiated by the script task.
pub load_data: LoadData,
/// The paint channel, cast to `Box<Any>`.
///
/// TODO(pcwalton): When we convert this to use IPC, this will need to become an
/// `IpcAnySender`.
pub paint_chan: Box<Any + Send>,
/// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an
/// `Sender<LayoutToPaintMsg>`.
pub paint_chan: OptionalOpaqueIpcSender,
/// Information on what to do on task failure.
pub failure: Failure,
/// A port on which layout can receive messages from the pipeline.
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
/// 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.
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum ScriptState {
/// The document has been loaded.
DocumentLoaded,
@ -100,6 +101,7 @@ pub enum ScriptState {
}
/// Messages sent from the constellation or layout to the script task.
#[derive(Deserialize, Serialize)]
pub enum ConstellationControlMsg {
/// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
AttachLayout(NewLayoutInfo),
@ -135,11 +137,11 @@ pub enum ConstellationControlMsg {
/// reflowed.
WebFontLoaded(PipelineId),
/// 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.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum MouseButton {
/// The left mouse button.
Left,
@ -150,7 +152,7 @@ pub enum MouseButton {
}
/// The type of input represented by a multi-touch event.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum TouchEventType {
/// A new touch point came in contact with the screen.
Down,
@ -165,10 +167,11 @@ pub enum TouchEventType {
/// An opaque identifier for a touch point.
///
/// 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);
/// Events from the compositor that the script task needs to know about
#[derive(Deserialize, Serialize)]
pub enum CompositorEvent {
/// The window was resized.
ResizeEvent(WindowSizeData),
@ -250,9 +253,9 @@ pub struct InitialScriptState {
/// The compositor.
pub compositor: IpcSender<ScriptToCompositorMsg>,
/// 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.
pub control_port: Receiver<ConstellationControlMsg>,
pub control_port: IpcReceiver<ConstellationControlMsg>,
/// A channel on which messages can be sent to the constellation from script.
pub constellation_chan: ConstellationChan<ConstellationMsg>,
/// A channel to schedule timer events.
@ -275,8 +278,14 @@ pub struct InitialScriptState {
pub window_size: Option<WindowSizeData>,
/// The ID of the pipeline namespace for this script thread.
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`
/// crate.
pub trait ScriptTaskFactory {

16
servo/components/servo/Cargo.lock сгенерированный
Просмотреть файл

@ -11,11 +11,13 @@ dependencies = [
"devtools_traits 0.0.1",
"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)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1",
"gfx_tests 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin_app 0.0.1",
"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)",
"layout 0.0.1",
"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)",
"devtools_traits 0.0.1",
"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_traits 0.0.1",
"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)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"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)",
"msg 0.0.1",
"net_traits 0.0.1",
@ -276,6 +280,8 @@ dependencies = [
"plugins 0.0.1",
"profile_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",
"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)",
@ -600,6 +606,16 @@ dependencies = [
"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]]
name = "gcc"
version = "0.3.16"

Просмотреть файл

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

Просмотреть файл

@ -17,6 +17,8 @@
// The `Browser` is fed events from a generic type that implements the
// `WindowMethods` trait.
extern crate gaol;
#[macro_use]
extern crate util as _util;
@ -29,6 +31,7 @@ mod export {
extern crate euclid;
extern crate gfx;
extern crate gleam;
extern crate ipc_channel;
extern crate layers;
extern crate layout;
extern crate msg;
@ -48,22 +51,25 @@ extern crate libc;
extern crate webdriver_server;
#[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: msg::constellation_msg::ConstellationChan<ConstellationMsg>) {
webdriver_server::start_server(port, constellation.clone());
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
webdriver_server::start_server(port, constellation);
}
#[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::compositor_task::InitialCompositorState;
use compositing::constellation::InitialConstellationState;
use compositing::pipeline::UnprivilegedPipelineContent;
use compositing::sandboxing;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorTask, Constellation};
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_task::FontCacheTask;
use ipc_channel::ipc::{self, IpcSender};
use msg::constellation_msg::CompositorMsg as ConstellationMsg;
use msg::constellation_msg::ConstellationChan;
use net::image_cache_task::new_image_cache_task;
use net::resource_task::new_resource_task;
use net::storage_task::StorageTaskFactory;
@ -86,6 +92,7 @@ pub use export::devtools_traits;
pub use export::euclid;
pub use export::gfx;
pub use export::gleam::gl;
pub use export::ipc_channel;
pub use export::layers;
pub use export::layout;
pub use export::msg;
@ -193,7 +200,7 @@ fn create_constellation(opts: opts::Opts,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
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 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.
match opts.url {
Some(url) => {
let ConstellationChan(ref chan) = constellation_chan;
chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
},
None => ()
};
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);
}

Просмотреть файл

@ -39,7 +39,7 @@ use offscreen_gl_context::GLContext;
use servo::Browser;
use servo::compositing::windowing::WindowEvent;
use servo::net_traits::hosts;
use servo::util::opts;
use servo::util::opts::{self, ArgumentParsingResult};
use std::rc::Rc;
#[cfg(not(target_os = "android"))]
@ -52,11 +52,17 @@ fn load_gl_when_headless() {}
fn main() {
// 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() {
::std::env::set_var("RUST_LOG", "compositing::constellation");
}
let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
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();
@ -65,6 +71,10 @@ fn main() {
// Possibly interpret the `HOST_FILE` environment variable
hosts::global_init();
if let Some(token) = content_process_token {
return servo::run_content_process(token)
}
let window = if opts::get().headless {
// Load gl functions even when in headless mode,
// to avoid crashing with webgl

Просмотреть файл

@ -2,18 +2,20 @@
* 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 ipc_channel::ipc::{self, IpcSender};
use ipc_channel::ipc::{self, IpcSender, OpaqueIpcSender};
use ipc_channel::router::ROUTER;
use opts;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::any::Any;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::marker::Reflect;
use std::mem;
use std::sync::Mutex;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
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());
}
@ -31,6 +33,17 @@ impl<T> OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
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 {
@ -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 {
fn deserialize<D>(deserializer: &mut D)
-> Result<OptionalIpcSender<T>, D::Error> where D: Deserializer {
if opts::get().multiprocess {
if opts::multiprocess() {
return Ok(OptionalIpcSender::OutOfProcess(try!(Deserialize::deserialize(
deserializer))))
}
let id: usize = try!(Deserialize::deserialize(deserializer));
let sender = (*IN_PROCESS_SENDERS.lock()
.unwrap()
.remove(&id)
.unwrap()
.downcast_ref::<Sender<T>>()
.unwrap()).clone();
Ok(OptionalIpcSender::InProcess(sender))
let sender = IN_PROCESS_SENDERS.lock().unwrap().remove(&id).unwrap();
Ok(OptionalIpcSender::InProcess(sender.to().unwrap()))
}
}
@ -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);
IN_PROCESS_SENDERS.lock()
.unwrap()
.insert(id, Box::new((*sender).clone()) as Box<Any + Send>);
.insert(id, OpaqueSender::new((*sender).clone()));
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>)
where T: Deserialize + Serialize + Send + Any {
if opts::get().multiprocess {
if opts::multiprocess() {
let (ipc_sender, ipc_receiver) = ipc::channel().unwrap();
let receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_receiver);
(OptionalIpcSender::OutOfProcess(ipc_sender), receiver)

Просмотреть файл

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

Просмотреть файл

@ -18,10 +18,11 @@ use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;
use std::process;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use url::{self, Url};
/// Global flags for Servo, currently set on the command line.
#[derive(Clone)]
#[derive(Clone, Deserialize, Serialize)]
pub struct Opts {
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.
pub user_agent: String,
/// Whether to run in multiprocess mode.
/// Whether we're running in multiprocess mode.
pub multiprocess: bool,
/// Whether we're running inside the sandbox.
pub sandbox: bool,
/// Dumps the flow tree after a layout.
pub dump_flow_tree: bool,
@ -375,6 +379,13 @@ static FORCE_CPU_PAINTING: bool = true;
#[cfg(not(target_os = "android"))]
static FORCE_CPU_PAINTING: bool = false;
static MULTIPROCESS: AtomicBool = ATOMIC_BOOL_INIT;
#[inline]
pub fn multiprocess() -> bool {
MULTIPROCESS.load(Ordering::Relaxed)
}
enum UserAgent {
Desktop,
Android,
@ -460,6 +471,7 @@ pub fn default_opts() -> Opts {
initial_window_size: Size2D::typed(800, 600),
user_agent: default_user_agent_string(DEFAULT_USER_AGENT),
multiprocess: false,
sandbox: false,
dump_flow_tree: false,
dump_display_list: 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 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)",
"NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)");
opts.optflag("M", "multiprocess", "Run in multiprocess mode");
opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess");
opts.optopt("Z", "debug",
"A comma-separated string of debug options. Pass help to show available options.", "");
opts.optflag("h", "help", "Print this message");
opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources");
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",
"A preference to set to enable", "dom.mozbrowser.enabled");
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);
};
// 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") {
Some(string) => string,
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") {
Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android),
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,
user_agent: user_agent,
multiprocess: opt_match.opt_present("M"),
sandbox: opt_match.opt_present("S"),
show_debug_borders: debug_options.show_compositor_borders,
show_debug_fragment_borders: debug_options.show_fragment_borders,
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() {
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

Просмотреть файл

@ -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 {
inner: String,
}

Просмотреть файл

@ -2,6 +2,8 @@
* 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 ipc_channel::ipc::IpcSender;
use serde::Serialize;
use std::borrow::ToOwned;
use std::sync::mpsc::Sender;
use std::thread;
@ -15,15 +17,36 @@ pub fn spawn_named<F>(name: String, f: F)
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.
pub fn spawn_named_with_send_on_failure<F, T>(name: String,
state: task_state::TaskState,
f: F,
msg: T,
dest: Sender<T>)
where F: FnOnce() + Send + 'static,
T: Send + 'static
{
pub fn spawn_named_with_send_on_failure<F, T, S>(name: String,
state: task_state::TaskState,
f: F,
msg: T,
mut dest: S)
where F: FnOnce() + Send + 'static,
T: Send + 'static,
S: Send + SendOnFailure<Value=T> + 'static {
let future_handle = thread::Builder::new().name(name.to_owned()).spawn(move || {
task_state::initialize(state);
f()
@ -35,8 +58,9 @@ pub fn spawn_named_with_send_on_failure<F, T>(name: String,
Ok(()) => (),
Err(..) => {
debug!("{} failed, notifying constellation", name);
dest.send(msg).unwrap();
dest.send_on_failure(msg);
}
}
}).unwrap();
}

Просмотреть файл

@ -28,7 +28,7 @@ use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use keys::keycodes_to_keys;
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::webdriver_msg::{LoadStatus, WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverScriptCommand};
use regex::Captures;
@ -37,6 +37,7 @@ use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::sync::mpsc::Sender;
use std::thread::{self, sleep_ms};
use url::Url;
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)]
}
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);
spawn_named("WebdriverHttpServer".to_owned(), move || {
server::start(SocketAddr::new("0.0.0.0".parse().unwrap(), port), handler,
@ -72,7 +73,7 @@ struct WebDriverSession {
struct Handler {
session: Option<WebDriverSession>,
constellation_chan: ConstellationChan<ConstellationMsg>,
constellation_chan: Sender<ConstellationMsg>,
script_timeout: u32,
load_timeout: u32,
implicit_wait_timeout: u32
@ -208,7 +209,7 @@ impl WebDriverSession {
}
impl Handler {
pub fn new(constellation_chan: ConstellationChan<ConstellationMsg>) -> Handler {
pub fn new(constellation_chan: Sender<ConstellationMsg>) -> Handler {
Handler {
session: None,
constellation_chan: constellation_chan,
@ -267,8 +268,7 @@ impl Handler {
fn pipeline(&self, frame_id: Option<FrameId>) -> Option<PipelineId> {
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap();
self.constellation_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap();
receiver.recv().unwrap()
@ -307,9 +307,8 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
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());
const_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
self.wait_for_load(sender, receiver)
}
@ -337,10 +336,9 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
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();
@ -348,14 +346,12 @@ impl Handler {
}
fn handle_go_back(&self) -> WebDriverResult<WebDriverResponse> {
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap();
self.constellation_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap();
Ok(WebDriverResponse::Void)
}
fn handle_go_forward(&self) -> WebDriverResult<WebDriverResponse> {
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Forward)).unwrap();
self.constellation_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Forward)).unwrap();
Ok(WebDriverResponse::Void)
}
@ -364,9 +360,8 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
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)
}
@ -375,10 +370,9 @@ impl Handler {
let pipeline_id = try!(self.root_pipeline());
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
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();
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
}
@ -406,10 +400,9 @@ impl Handler {
}
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender);
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() {
Ok(value) => {
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 cmd = WebDriverScriptCommand::GetFrameId(frame_id, sender);
{
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::WebDriverCommand(
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(
WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap();
}
let frame = match receiver.recv().unwrap() {
Ok(Some(pipeline_id)) => {
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::GetFrame(pipeline_id, sender)).unwrap();
self.constellation_chan.send(ConstellationMsg::GetFrame(pipeline_id, sender)).unwrap();
receiver.recv().unwrap()
},
Ok(None) => None,
@ -481,10 +472,9 @@ impl Handler {
}
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender);
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() {
Ok(value) => {
let resp_value: Vec<Json> = value.into_iter().map(
@ -500,10 +490,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender);
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() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -515,10 +504,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetActiveElement(sender);
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());
Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json())))
}
@ -527,10 +515,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline());
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender);
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() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -542,10 +529,9 @@ impl Handler {
let pipeline_id = try!(self.frame_pipeline());
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_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() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference,
@ -601,9 +587,8 @@ impl Handler {
-> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.frame_pipeline());
let ConstellationChan(ref const_chan) = self.constellation_chan;
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() {
Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new(value.to_json()))),
@ -618,12 +603,11 @@ impl Handler {
keys: &SendKeysParameters) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.frame_pipeline());
let ConstellationChan(ref const_chan) = self.constellation_chan;
let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::FocusElement(element.id.clone(), sender);
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
try!(receiver.recv().unwrap().or_else(|_| Err(WebDriverError::new(
@ -633,7 +617,7 @@ impl Handler {
Err(WebDriverError::new(ErrorStatus::UnsupportedOperation, "Failed to convert keycodes"))));
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)
}
@ -647,9 +631,8 @@ impl Handler {
for _ in 0..iterations {
let (sender, receiver) = ipc::channel().unwrap();
let ConstellationChan(ref const_chan) = self.constellation_chan;
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() {
img = Some(x);

16
servo/ports/cef/Cargo.lock сгенерированный
Просмотреть файл

@ -253,6 +253,7 @@ dependencies = [
"core-text 0.1.0 (git+https://github.com/servo/core-text-rs)",
"devtools_traits 0.0.1",
"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_traits 0.0.1",
"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)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"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)",
"msg 0.0.1",
"net_traits 0.0.1",
@ -268,6 +270,8 @@ dependencies = [
"plugins 0.0.1",
"profile_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",
"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)",
@ -559,6 +563,16 @@ dependencies = [
"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]]
name = "gcc"
version = "0.3.16"
@ -1555,9 +1569,11 @@ dependencies = [
"devtools_traits 0.0.1",
"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)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1",
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"layout 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",

16
servo/ports/gonk/Cargo.lock сгенерированный
Просмотреть файл

@ -245,6 +245,7 @@ dependencies = [
"core-text 0.1.0 (git+https://github.com/servo/core-text-rs)",
"devtools_traits 0.0.1",
"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_traits 0.0.1",
"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)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"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)",
"msg 0.0.1",
"net_traits 0.0.1",
@ -260,6 +262,8 @@ dependencies = [
"plugins 0.0.1",
"profile_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",
"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)",
@ -561,6 +565,16 @@ dependencies = [
"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]]
name = "gcc"
version = "0.3.16"
@ -1535,8 +1549,10 @@ dependencies = [
"devtools_traits 0.0.1",
"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)",
"gaol 0.0.1 (git+https://github.com/pcwalton/gaol)",
"gfx 0.0.1",
"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)",
"layout 0.0.1",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",