зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
a4e688b2a0
Коммит
8c7de61738
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)",
|
||||
|
|
|
@ -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)",
|
||||
|
|
Загрузка…
Ссылка в новой задаче