devtools: Convert the developer tools to run over IPC.

This commit is contained in:
Patrick Walton 2015-07-25 00:24:56 -07:00
parent e13ebf712d
commit 164e10202c
26 changed files with 295 additions and 141 deletions

View file

@ -20,8 +20,17 @@ path = "../msg"
[dependencies.util]
path = "../util"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies.url]
version = "0.2"
features = [ "serde_serialization" ]
[dependencies]
log = "0.3"
time = "0.1"
rustc-serialize = "0.3"
url = "0.2"
serde = "0.4"
serde_macros = "0.4"

View file

@ -4,6 +4,7 @@
/// General actor system infrastructure.
use devtools_traits::PreciseTime;
use rustc_serialize::json;
use std::any::{Any, TypeId};
use std::collections::HashMap;
@ -13,7 +14,6 @@ use std::mem::{replace, transmute};
use std::net::TcpStream;
use std::raw::TraitObject;
use std::sync::{Arc, Mutex};
use time::PreciseTime;
/// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors.

View file

@ -18,9 +18,10 @@ use msg::constellation_msg::PipelineId;
use std::collections::BTreeMap;
use core::cell::RefCell;
use ipc_channel::ipc::{self, IpcSender};
use rustc_serialize::json::{self, Json, ToJson};
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender};
use std::sync::mpsc::channel;
trait EncodableConsoleMessage {
fn encode(&self) -> json::EncodeResult<String>;
@ -81,7 +82,7 @@ struct EvaluateJSReply {
pub struct ConsoleActor {
pub name: String,
pub pipeline: PipelineId,
pub script_chan: Sender<DevtoolScriptControlMsg>,
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
pub streams: RefCell<Vec<TcpStream>>,
}
@ -108,7 +109,7 @@ impl Actor for ConsoleActor {
s => println!("unrecognized message type requested: \"{}\"", s),
};
};
let (chan, port) = channel();
let (chan, port) = ipc::channel().unwrap();
self.script_chan.send(DevtoolScriptControlMsg::GetCachedMessages(
self.pipeline, message_types, chan)).unwrap();
let messages = try!(port.recv().map_err(|_| ())).into_iter().map(|message| {
@ -170,7 +171,7 @@ impl Actor for ConsoleActor {
"evaluateJS" => {
let input = msg.get(&"text".to_string()).unwrap().as_string().unwrap().to_string();
let (chan, port) = channel();
let (chan, port) = ipc::channel().unwrap();
self.script_chan.send(DevtoolScriptControlMsg::EvaluateJS(
self.pipeline, input.clone(), chan)).unwrap();

View file

@ -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::{self, IpcSender};
use ipc_channel::router::ROUTER;
use rustc_serialize::json;
use std::mem;
use std::net::TcpStream;
@ -12,12 +14,12 @@ use time::precise_time_ns;
use msg::constellation_msg::PipelineId;
use actor::{Actor, ActorRegistry};
use actors::timeline::HighResolutionStamp;
use devtools_traits::{DevtoolsControlMsg, DevtoolScriptControlMsg};
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, DevtoolScriptControlMsg};
pub struct FramerateActor {
name: String,
pipeline: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>,
start_time: Option<u64>,
is_recording: Arc<Mutex<bool>>,
@ -43,7 +45,7 @@ impl FramerateActor {
/// return name of actor
pub fn create(registry: &ActorRegistry,
pipeline_id: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>) -> String {
let actor_name = registry.new_name("framerate");
let mut actor = FramerateActor {
@ -86,12 +88,13 @@ impl FramerateActor {
fn get_closure(is_recording: Arc<Mutex<bool>>,
name: String,
pipeline: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>)
-> Box<Fn(f64, ) + Send> {
let closure = move |now: f64| {
let msg = DevtoolsControlMsg::FramerateTick(name.clone(), now);
let msg = DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::FramerateTick(
name.clone(), now));
devtools_sender.send(msg).unwrap();
if !*is_recording.lock().unwrap() {
@ -103,7 +106,15 @@ impl FramerateActor {
pipeline.clone(),
script_sender.clone(),
devtools_sender.clone());
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(pipeline, closure);
let (request_animation_frame_sender, request_animation_frame_receiver) =
ipc::channel().unwrap();
ROUTER.add_route(request_animation_frame_receiver.to_opaque(), box move |message| {
let value: f64 = message.to().unwrap();
closure(value);
});
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(
pipeline,
request_animation_frame_sender);
script_sender.send(msg).unwrap();
};
Box::new(closure)
@ -114,7 +125,14 @@ impl FramerateActor {
self.pipeline.clone(),
self.script_sender.clone(),
self.devtools_sender.clone());
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, closure);
let (request_animation_frame_sender, request_animation_frame_receiver) =
ipc::channel().unwrap();
ROUTER.add_route(request_animation_frame_receiver.to_opaque(), box move |message| {
let value: f64 = message.to().unwrap();
closure(value);
});
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline,
request_animation_frame_sender);
self.script_sender.send(msg).unwrap();
}

View file

@ -12,19 +12,20 @@ use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute};
use actor::{Actor, ActorRegistry};
use protocol::JsonPacketStream;
use ipc_channel::ipc::{self, IpcSender};
use std::collections::BTreeMap;
use msg::constellation_msg::PipelineId;
use rustc_serialize::json::{self, Json, ToJson};
use std::cell::RefCell;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender};
use std::sync::mpsc::channel;
pub struct InspectorActor {
pub name: String,
pub walker: RefCell<Option<String>>,
pub pageStyle: RefCell<Option<String>>,
pub highlighter: RefCell<Option<String>>,
pub script_chan: Sender<DevtoolScriptControlMsg>,
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
pub pipeline: PipelineId,
}
@ -45,7 +46,7 @@ struct HighlighterActor {
pub struct NodeActor {
pub name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
@ -181,7 +182,7 @@ trait NodeInfoToProtocol {
fn encode(self,
actors: &ActorRegistry,
display: bool,
script_chan: Sender<DevtoolScriptControlMsg>,
script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId) -> NodeActorMsg;
}
@ -189,7 +190,7 @@ impl NodeInfoToProtocol for NodeInfo {
fn encode(self,
actors: &ActorRegistry,
display: bool,
script_chan: Sender<DevtoolScriptControlMsg>,
script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId) -> NodeActorMsg {
let actor_name = if !actors.script_actor_registered(self.uniqueId.clone()) {
let name = actors.new_name("node");
@ -242,7 +243,7 @@ impl NodeInfoToProtocol for NodeInfo {
struct WalkerActor {
name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
@ -290,7 +291,7 @@ impl Actor for WalkerActor {
}
"documentElement" => {
let (tx, rx) = channel();
let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetDocumentElement(self.pipeline, tx)).unwrap();
let doc_elem_info = rx.recv().unwrap();
let node = doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline);
@ -313,7 +314,7 @@ impl Actor for WalkerActor {
"children" => {
let target = msg.get(&"node".to_string()).unwrap().as_string().unwrap();
let (tx, rx) = channel();
let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetChildren(self.pipeline,
registry.actor_to_script(target.to_string()),
tx))
@ -350,7 +351,7 @@ struct PageStyleMsg {
struct PageStyleActor {
name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
@ -452,7 +453,7 @@ impl Actor for PageStyleActor {
//TODO: query script for box layout properties of node (msg.node)
"getLayout" => {
let target = msg.get(&"node".to_string()).unwrap().as_string().unwrap();
let (tx, rx) = channel();
let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetLayout(self.pipeline,
registry.actor_to_script(target.to_string()),
tx))
@ -514,7 +515,7 @@ impl Actor for InspectorActor {
registry.register_later(box walker);
}
let (tx, rx) = channel();
let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetRootNode(self.pipeline, tx)).unwrap();
let root_info = rx.recv().unwrap();

View file

@ -2,6 +2,7 @@
* 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, IpcReceiver, IpcSender};
use msg::constellation_msg::PipelineId;
use rustc_serialize::{json, Encoder, Encodable};
use std::cell::RefCell;
@ -10,21 +11,20 @@ use std::mem;
use std::net::TcpStream;
use std::thread::sleep_ms;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use time::PreciseTime;
use std::sync::mpsc::{channel, Sender};
use actor::{Actor, ActorRegistry};
use actors::memory::{MemoryActor, TimelineMemoryReply};
use actors::framerate::FramerateActor;
use devtools_traits::{DevtoolsControlMsg, DevtoolScriptControlMsg};
use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers};
use devtools_traits::{TimelineMarker, TracingMetadata, TimelineMarkerType};
use devtools_traits::{PreciseTime, TimelineMarker, TracingMetadata, TimelineMarkerType};
use protocol::JsonPacketStream;
use util::task;
pub struct TimelineActor {
name: String,
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>,
marker_types: Vec<TimelineMarkerType>,
pipeline: PipelineId,
@ -126,7 +126,7 @@ static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u32 = 200; //ms
impl TimelineActor {
pub fn new(name: String,
pipeline: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>) -> TimelineActor {
let marker_types = vec!(TimelineMarkerType::Reflow,
@ -146,7 +146,7 @@ impl TimelineActor {
}
}
fn pull_timeline_data(&self, receiver: Receiver<TimelineMarker>, mut emitter: Emitter) {
fn pull_timeline_data(&self, receiver: IpcReceiver<TimelineMarker>, mut emitter: Emitter) {
let is_recording = self.is_recording.clone();
if !*is_recording.lock().unwrap() {
@ -240,8 +240,10 @@ impl Actor for TimelineActor {
"start" => {
**self.is_recording.lock().as_mut().unwrap() = true;
let (tx, rx) = channel::<TimelineMarker>();
self.script_sender.send(SetTimelineMarkers(self.pipeline, self.marker_types.clone(), tx)).unwrap();
let (tx, rx) = ipc::channel::<TimelineMarker>().unwrap();
self.script_sender.send(SetTimelineMarkers(self.pipeline,
self.marker_types.clone(),
tx)).unwrap();
*self.stream.borrow_mut() = stream.try_clone().ok();
@ -255,10 +257,11 @@ impl Actor for TimelineActor {
// init framerate actor
if let Some(with_ticks) = msg.get("withTicks") {
if let Some(true) = with_ticks.as_boolean() {
let framerate_actor = Some(FramerateActor::create(registry,
self.pipeline.clone(),
self.script_sender.clone(),
self.devtools_sender.clone()));
let framerate_actor = Some(FramerateActor::create(
registry,
self.pipeline.clone(),
self.script_sender.clone(),
self.devtools_sender.clone()));
*self.framerate_actor.borrow_mut() = framerate_actor;
}
}

View file

@ -12,9 +12,12 @@
#![feature(box_syntax)]
#![feature(core)]
#![feature(custom_derive)]
#![feature(get_type_id)]
#![feature(plugin)]
#![feature(raw)]
#![feature(reflect_marker)]
#![plugin(serde_macros)]
#![allow(non_snake_case)]
@ -24,6 +27,8 @@ extern crate log;
extern crate core;
extern crate devtools_traits;
extern crate rustc_serialize;
extern crate ipc_channel;
extern crate serde;
extern crate msg;
extern crate time;
extern crate util;
@ -41,11 +46,13 @@ use actors::timeline::TimelineActor;
use actors::worker::WorkerActor;
use protocol::JsonPacketStream;
use devtools_traits::{ConsoleMessage, DevtoolsControlMsg, NetworkEvent, LogLevel};
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg};
use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg};
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg, LogLevel, NetworkEvent};
use devtools_traits::{ScriptToDevtoolsControlMsg};
use msg::constellation_msg::{PipelineId, WorkerId};
use util::task::spawn_named;
use ipc_channel::ipc::IpcSender;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::collections::HashMap;
@ -184,7 +191,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
// TODO: move this into the root or tab modules?
fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
ids: (PipelineId, Option<WorkerId>),
script_sender: Sender<DevtoolScriptControlMsg>,
script_sender: IpcSender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>,
actor_pipelines: &mut HashMap<PipelineId, String>,
actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
@ -371,28 +378,34 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
// accept connections and process them, spawning a new task for each one
for stream in listener.incoming() {
// connection succeeded
sender_clone.send(DevtoolsControlMsg::AddClient(stream.unwrap())).unwrap();
sender_clone.send(DevtoolsControlMsg::FromChrome(
ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()))).unwrap();
}
});
loop {
match receiver.recv() {
Ok(DevtoolsControlMsg::AddClient(stream)) => {
Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream))) => {
let actors = actors.clone();
accepted_connections.push(stream.try_clone().unwrap());
spawn_named("DevtoolsClientHandler".to_owned(), move || {
handle_client(actors, stream.try_clone().unwrap())
})
}
Ok(DevtoolsControlMsg::FramerateTick(actor_name, tick)) =>
Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::FramerateTick(
actor_name, tick))) =>
handle_framerate_tick(actors.clone(), actor_name, tick),
Ok(DevtoolsControlMsg::NewGlobal(ids, script_sender, pageinfo)) =>
Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
ids, script_sender, pageinfo))) =>
handle_new_global(actors.clone(), ids, script_sender, sender.clone(), &mut actor_pipelines,
&mut actor_workers, pageinfo),
Ok(DevtoolsControlMsg::SendConsoleMessage(id, console_message)) =>
Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::SendConsoleMessage(
id,
console_message))) =>
handle_console_message(actors.clone(), id, console_message,
&actor_pipelines),
Ok(DevtoolsControlMsg::NetworkEventMessage(request_id, network_event)) => {
Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEventMessage(
request_id, network_event))) => {
// copy the accepted_connections vector
let mut connections = Vec::<TcpStream>::new();
for stream in accepted_connections.iter() {
@ -403,7 +416,8 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests,
PipelineId(0), request_id, network_event);
},
Ok(DevtoolsControlMsg::ServerExitMsg) | Err(RecvError) => break
Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg)) |
Err(RecvError) => break
}
}
for connection in accepted_connections.iter_mut() {