Format components devtools and devtools_traits #21373

This commit is contained in:
kingdido999 2018-09-02 20:29:47 +08:00
parent b211e45bb0
commit ad822b74c7
17 changed files with 669 additions and 461 deletions

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// General actor system infrastructure. /// General actor system infrastructure.
use devtools_traits::PreciseTime; use devtools_traits::PreciseTime;
use serde_json::{Map, Value}; use serde_json::{Map, Value};
use std::any::Any; use std::any::Any;
@ -23,11 +22,13 @@ pub enum ActorMessageStatus {
/// and the ability to process messages that are directed to particular actors. /// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable /// TODO: ensure the name is immutable
pub trait Actor: Any + ActorAsAny { pub trait Actor: Any + ActorAsAny {
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()>; msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()>;
fn name(&self) -> String; fn name(&self) -> String;
} }
@ -37,8 +38,12 @@ pub trait ActorAsAny {
} }
impl<T: Actor> ActorAsAny for T { impl<T: Actor> ActorAsAny for T {
fn actor_as_any(&self) -> &Any { self } fn actor_as_any(&self) -> &Any {
fn actor_as_any_mut(&mut self) -> &mut Any { self } self
}
fn actor_as_any_mut(&mut self) -> &mut Any {
self
}
} }
/// A list of known, owned actors. /// A list of known, owned actors.
@ -57,8 +62,8 @@ impl ActorRegistry {
pub fn new() -> ActorRegistry { pub fn new() -> ActorRegistry {
ActorRegistry { ActorRegistry {
actors: HashMap::new(), actors: HashMap::new(),
new_actors: RefCell::new(vec!()), new_actors: RefCell::new(vec![]),
old_actors: RefCell::new(vec!()), old_actors: RefCell::new(vec![]),
script_actors: RefCell::new(HashMap::new()), script_actors: RefCell::new(HashMap::new()),
shareable: None, shareable: None,
next: Cell::new(0), next: Cell::new(0),
@ -149,29 +154,33 @@ impl ActorRegistry {
/// Attempt to process a message as directed by its `to` property. If the actor is not /// Attempt to process a message as directed by its `to` property. If the actor is not
/// found or does not indicate that it knew how to process the message, ignore the failure. /// found or does not indicate that it knew how to process the message, ignore the failure.
pub fn handle_message(&mut self, pub fn handle_message(
msg: &Map<String, Value>, &mut self,
stream: &mut TcpStream) msg: &Map<String, Value>,
-> Result<(), ()> { stream: &mut TcpStream,
) -> Result<(), ()> {
let to = msg.get("to").unwrap().as_str().unwrap(); let to = msg.get("to").unwrap().as_str().unwrap();
match self.actors.get(to) { match self.actors.get(to) {
None => debug!("message received for unknown actor \"{}\"", to), None => debug!("message received for unknown actor \"{}\"", to),
Some(actor) => { Some(actor) => {
let msg_type = msg.get("type").unwrap().as_str().unwrap(); let msg_type = msg.get("type").unwrap().as_str().unwrap();
if actor.handle_message(self, msg_type, msg, stream)? if actor.handle_message(self, msg_type, msg, stream)? !=
!= ActorMessageStatus::Processed { ActorMessageStatus::Processed
debug!("unexpected message type \"{}\" found for actor \"{}\"", {
msg_type, to); debug!(
"unexpected message type \"{}\" found for actor \"{}\"",
msg_type, to
);
} }
} },
} }
let new_actors = replace(&mut *self.new_actors.borrow_mut(), vec!()); let new_actors = replace(&mut *self.new_actors.borrow_mut(), vec![]);
for actor in new_actors.into_iter() { for actor in new_actors.into_iter() {
self.actors.insert(actor.name().to_owned(), actor); self.actors.insert(actor.name().to_owned(), actor);
} }
let old_actors = replace(&mut *self.old_actors.borrow_mut(), vec!()); let old_actors = replace(&mut *self.old_actors.borrow_mut(), vec![]);
for name in old_actors { for name in old_actors {
self.drop_actor(name); self.drop_actor(name);
} }

View file

@ -94,32 +94,48 @@ impl Actor for ConsoleActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"getCachedMessages" => { "getCachedMessages" => {
let str_types = msg.get("messageTypes").unwrap().as_array().unwrap().into_iter().map(|json_type| { let str_types = msg
json_type.as_str().unwrap() .get("messageTypes")
}); .unwrap()
.as_array()
.unwrap()
.into_iter()
.map(|json_type| json_type.as_str().unwrap());
let mut message_types = CachedConsoleMessageTypes::empty(); let mut message_types = CachedConsoleMessageTypes::empty();
for str_type in str_types { for str_type in str_types {
match str_type { match str_type {
"PageError" => message_types.insert(CachedConsoleMessageTypes::PAGE_ERROR), "PageError" => message_types.insert(CachedConsoleMessageTypes::PAGE_ERROR),
"ConsoleAPI" => message_types.insert(CachedConsoleMessageTypes::CONSOLE_API), "ConsoleAPI" => {
message_types.insert(CachedConsoleMessageTypes::CONSOLE_API)
},
s => debug!("unrecognized message type requested: \"{}\"", s), s => debug!("unrecognized message type requested: \"{}\"", s),
}; };
}; }
let (chan, port) = ipc::channel().unwrap(); let (chan, port) = ipc::channel().unwrap();
self.script_chan.send(DevtoolScriptControlMsg::GetCachedMessages( self.script_chan
self.pipeline, message_types, chan)).unwrap(); .send(DevtoolScriptControlMsg::GetCachedMessages(
let messages = port.recv().map_err(|_| ())?.into_iter().map(|message| { self.pipeline,
let json_string = message.encode().unwrap(); message_types,
let json = serde_json::from_str::<Value>(&json_string).unwrap(); chan,
json.as_object().unwrap().to_owned() )).unwrap();
}).collect(); let messages = port
.recv()
.map_err(|_| ())?
.into_iter()
.map(|message| {
let json_string = message.encode().unwrap();
let json = serde_json::from_str::<Value>(&json_string).unwrap();
json.as_object().unwrap().to_owned()
}).collect();
let msg = GetCachedMessagesReply { let msg = GetCachedMessagesReply {
from: self.name(), from: self.name(),
@ -127,56 +143,60 @@ impl Actor for ConsoleActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"startListeners" => { "startListeners" => {
//TODO: actually implement listener filters that support starting/stopping //TODO: actually implement listener filters that support starting/stopping
let msg = StartedListenersReply { let msg = StartedListenersReply {
from: self.name(), from: self.name(),
nativeConsoleAPI: true, nativeConsoleAPI: true,
startedListeners: startedListeners: vec!["PageError".to_owned(), "ConsoleAPI".to_owned()],
vec!("PageError".to_owned(), "ConsoleAPI".to_owned()),
traits: StartedListenersTraits { traits: StartedListenersTraits {
customNetworkRequest: true, customNetworkRequest: true,
} },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"stopListeners" => { "stopListeners" => {
//TODO: actually implement listener filters that support starting/stopping //TODO: actually implement listener filters that support starting/stopping
let msg = StopListenersReply { let msg = StopListenersReply {
from: self.name(), from: self.name(),
stoppedListeners: msg.get("listeners") stoppedListeners: msg
.unwrap() .get("listeners")
.as_array() .unwrap()
.unwrap_or(&vec!()) .as_array()
.iter() .unwrap_or(&vec![])
.map(|listener| listener.as_str().unwrap().to_owned()) .iter()
.collect(), .map(|listener| listener.as_str().unwrap().to_owned())
.collect(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
//TODO: implement autocompletion like onAutocomplete in //TODO: implement autocompletion like onAutocomplete in
// http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webconsole.js // http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webconsole.js
"autocomplete" => { "autocomplete" => {
let msg = AutocompleteReply { let msg = AutocompleteReply {
from: self.name(), from: self.name(),
matches: vec!(), matches: vec![],
matchProp: "".to_owned(), matchProp: "".to_owned(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"evaluateJS" => { "evaluateJS" => {
let input = msg.get("text").unwrap().as_str().unwrap().to_owned(); let input = msg.get("text").unwrap().as_str().unwrap().to_owned();
let (chan, port) = ipc::channel().unwrap(); let (chan, port) = ipc::channel().unwrap();
self.script_chan.send(DevtoolScriptControlMsg::EvaluateJS( self.script_chan
self.pipeline, input.clone(), chan)).unwrap(); .send(DevtoolScriptControlMsg::EvaluateJS(
self.pipeline,
input.clone(),
chan,
)).unwrap();
//TODO: extract conversion into protocol module or some other useful place //TODO: extract conversion into protocol module or some other useful place
let result = match port.recv().map_err(|_| ())? { let result = match port.recv().map_err(|_| ())? {
@ -184,12 +204,12 @@ impl Actor for ConsoleActor {
let mut m = Map::new(); let mut m = Map::new();
m.insert("type".to_owned(), Value::String("undefined".to_owned())); m.insert("type".to_owned(), Value::String("undefined".to_owned()));
Value::Object(m) Value::Object(m)
} },
NullValue => { NullValue => {
let mut m = Map::new(); let mut m = Map::new();
m.insert("type".to_owned(), Value::String("null".to_owned())); m.insert("type".to_owned(), Value::String("null".to_owned()));
Value::Object(m) Value::Object(m)
} },
BooleanValue(val) => Value::Bool(val), BooleanValue(val) => Value::Bool(val),
NumberValue(val) => { NumberValue(val) => {
if val.is_nan() { if val.is_nan() {
@ -211,7 +231,7 @@ impl Actor for ConsoleActor {
} else { } else {
Value::Number(Number::from_f64(val).unwrap()) Value::Number(Number::from_f64(val).unwrap())
} }
} },
StringValue(s) => Value::String(s), StringValue(s) => Value::String(s),
ActorValue { class, uuid } => { ActorValue { class, uuid } => {
//TODO: make initial ActorValue message include these properties? //TODO: make initial ActorValue message include these properties?
@ -225,7 +245,7 @@ impl Actor for ConsoleActor {
m.insert("frozen".to_owned(), Value::Bool(false)); m.insert("frozen".to_owned(), Value::Bool(false));
m.insert("sealed".to_owned(), Value::Bool(false)); m.insert("sealed".to_owned(), Value::Bool(false));
Value::Object(m) Value::Object(m)
} },
}; };
//TODO: catch and return exception values from JS evaluation //TODO: catch and return exception values from JS evaluation
@ -240,7 +260,7 @@ impl Actor for ConsoleActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"setPreferences" => { "setPreferences" => {
let msg = SetPreferencesReply { let msg = SetPreferencesReply {
@ -249,9 +269,9 @@ impl Actor for ConsoleActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored _ => ActorMessageStatus::Ignored,
}) })
} }
} }

View file

@ -26,21 +26,24 @@ impl Actor for FramerateActor {
self.name.clone() self.name.clone()
} }
fn handle_message(
fn handle_message(&self, &self,
_registry: &ActorRegistry, _registry: &ActorRegistry,
_msg_type: &str, _msg_type: &str,
_msg: &Map<String, Value>, _msg: &Map<String, Value>,
_stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Ignored) Ok(ActorMessageStatus::Ignored)
} }
} }
impl FramerateActor { impl FramerateActor {
/// return name of actor /// return name of actor
pub fn create(registry: &ActorRegistry, pub fn create(
pipeline_id: PipelineId, registry: &ActorRegistry,
script_sender: IpcSender<DevtoolScriptControlMsg>) -> String { pipeline_id: PipelineId,
script_sender: IpcSender<DevtoolScriptControlMsg>,
) -> String {
let actor_name = registry.new_name("framerate"); let actor_name = registry.new_name("framerate");
let mut actor = FramerateActor { let mut actor = FramerateActor {
name: actor_name.clone(), name: actor_name.clone(),
@ -60,8 +63,7 @@ impl FramerateActor {
self.ticks.push(HighResolutionStamp::wrap(tick)); self.ticks.push(HighResolutionStamp::wrap(tick));
if self.is_recording { if self.is_recording {
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, self.name());
self.name());
self.script_sender.send(msg).unwrap(); self.script_sender.send(msg).unwrap();
} }
} }
@ -78,8 +80,7 @@ impl FramerateActor {
self.start_time = Some(precise_time_ns()); self.start_time = Some(precise_time_ns());
self.is_recording = true; self.is_recording = true;
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, self.name());
self.name());
self.script_sender.send(msg).unwrap(); self.script_sender.send(msg).unwrap();
} }
@ -90,7 +91,6 @@ impl FramerateActor {
self.is_recording = false; self.is_recording = false;
self.start_time = None; self.start_time = None;
} }
} }
impl Drop for FramerateActor { impl Drop for FramerateActor {

View file

@ -61,27 +61,25 @@ impl Actor for HighlighterActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_registry: &ActorRegistry, &self,
msg_type: &str, _registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"showBoxModel" => { "showBoxModel" => {
let msg = ShowBoxModelReply { let msg = ShowBoxModelReply { from: self.name() };
from: self.name(),
};
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"hideBoxModel" => { "hideBoxModel" => {
let msg = HideBoxModelReply { let msg = HideBoxModelReply { from: self.name() };
from: self.name(),
};
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })
@ -98,29 +96,33 @@ impl Actor for NodeActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"modifyAttributes" => { "modifyAttributes" => {
let target = msg.get("to").unwrap().as_str().unwrap(); let target = msg.get("to").unwrap().as_str().unwrap();
let mods = msg.get("modifications").unwrap().as_array().unwrap(); let mods = msg.get("modifications").unwrap().as_array().unwrap();
let modifications = mods.iter().map(|json_mod| { let modifications = mods
serde_json::from_str(&serde_json::to_string(json_mod).unwrap()).unwrap() .iter()
}).collect(); .map(|json_mod| {
serde_json::from_str(&serde_json::to_string(json_mod).unwrap()).unwrap()
}).collect();
self.script_chan.send(ModifyAttribute(self.pipeline, self.script_chan
registry.actor_to_script(target.to_owned()), .send(ModifyAttribute(
modifications)) self.pipeline,
.unwrap(); registry.actor_to_script(target.to_owned()),
let reply = ModifyAttributeReply { modifications,
from: self.name(), )).unwrap();
}; let reply = ModifyAttributeReply { from: self.name() };
stream.write_json_packet(&reply); stream.write_json_packet(&reply);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })
@ -175,19 +177,23 @@ struct NodeActorMsg {
} }
trait NodeInfoToProtocol { trait NodeInfoToProtocol {
fn encode(self, fn encode(
actors: &ActorRegistry, self,
display: bool, actors: &ActorRegistry,
script_chan: IpcSender<DevtoolScriptControlMsg>, display: bool,
pipeline: PipelineId) -> NodeActorMsg; script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
) -> NodeActorMsg;
} }
impl NodeInfoToProtocol for NodeInfo { impl NodeInfoToProtocol for NodeInfo {
fn encode(self, fn encode(
actors: &ActorRegistry, self,
display: bool, actors: &ActorRegistry,
script_chan: IpcSender<DevtoolScriptControlMsg>, display: bool,
pipeline: PipelineId) -> NodeActorMsg { script_chan: IpcSender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
) -> NodeActorMsg {
let actor_name = if !actors.script_actor_registered(self.uniqueId.clone()) { let actor_name = if !actors.script_actor_registered(self.uniqueId.clone()) {
let name = actors.new_name("node"); let name = actors.new_name("node");
let node_actor = NodeActor { let node_actor = NodeActor {
@ -215,15 +221,16 @@ impl NodeInfoToProtocol for NodeInfo {
publicId: self.publicId, publicId: self.publicId,
systemId: self.systemId, systemId: self.systemId,
attrs: self.attrs.into_iter().map(|attr| { attrs: self
AttrMsg { .attrs
.into_iter()
.map(|attr| AttrMsg {
namespace: attr.namespace, namespace: attr.namespace,
name: attr.name, name: attr.name,
value: attr.value, value: attr.value,
} }).collect(),
}).collect(),
pseudoClassLocks: vec!(), //TODO get this data from script pseudoClassLocks: vec![], //TODO get this data from script
isDisplayed: display, isDisplayed: display,
@ -272,25 +279,28 @@ impl Actor for WalkerActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"querySelector" => { "querySelector" => {
let msg = QuerySelectorReply { let msg = QuerySelectorReply { from: self.name() };
from: self.name(),
};
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"documentElement" => { "documentElement" => {
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetDocumentElement(self.pipeline, tx)).unwrap(); self.script_chan
.send(GetDocumentElement(self.pipeline, tx))
.unwrap();
let doc_elem_info = rx.recv().unwrap().ok_or(())?; let doc_elem_info = rx.recv().unwrap().ok_or(())?;
let node = doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline); let node =
doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline);
let msg = DocumentElementReply { let msg = DocumentElementReply {
from: self.name(), from: self.name(),
@ -298,36 +308,38 @@ impl Actor for WalkerActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"clearPseudoClassLocks" => { "clearPseudoClassLocks" => {
let msg = ClearPseudoclassesReply { let msg = ClearPseudoclassesReply { from: self.name() };
from: self.name(),
};
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"children" => { "children" => {
let target = msg.get("node").unwrap().as_str().unwrap(); let target = msg.get("node").unwrap().as_str().unwrap();
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetChildren(self.pipeline, self.script_chan
registry.actor_to_script(target.to_owned()), .send(GetChildren(
tx)) self.pipeline,
.unwrap(); registry.actor_to_script(target.to_owned()),
tx,
)).unwrap();
let children = rx.recv().unwrap().ok_or(())?; let children = rx.recv().unwrap().ok_or(())?;
let msg = ChildrenReply { let msg = ChildrenReply {
hasFirst: true, hasFirst: true,
hasLast: true, hasLast: true,
nodes: children.into_iter().map(|child| { nodes: children
child.encode(registry, true, self.script_chan.clone(), self.pipeline) .into_iter()
}).collect(), .map(|child| {
child.encode(registry, true, self.script_chan.clone(), self.pipeline)
}).collect(),
from: self.name(), from: self.name(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })
@ -447,52 +459,72 @@ impl Actor for PageStyleActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"getApplied" => { "getApplied" => {
//TODO: query script for relevant applied styles to node (msg.node) //TODO: query script for relevant applied styles to node (msg.node)
let msg = GetAppliedReply { let msg = GetAppliedReply {
entries: vec!(), entries: vec![],
rules: vec!(), rules: vec![],
sheets: vec!(), sheets: vec![],
from: self.name(), from: self.name(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getComputed" => { "getComputed" => {
//TODO: query script for relevant computed styles on node (msg.node) //TODO: query script for relevant computed styles on node (msg.node)
let msg = GetComputedReply { let msg = GetComputedReply {
computed: vec!(), computed: vec![],
from: self.name(), from: self.name(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
//TODO: query script for box layout properties of node (msg.node) //TODO: query script for box layout properties of node (msg.node)
"getLayout" => { "getLayout" => {
let target = msg.get("node").unwrap().as_str().unwrap(); let target = msg.get("node").unwrap().as_str().unwrap();
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetLayout(self.pipeline, self.script_chan
registry.actor_to_script(target.to_owned()), .send(GetLayout(
tx)) self.pipeline,
.unwrap(); registry.actor_to_script(target.to_owned()),
tx,
)).unwrap();
let ComputedNodeLayout { let ComputedNodeLayout {
display, position, zIndex, boxSizing, display,
autoMargins, marginTop, marginRight, marginBottom, marginLeft, position,
borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, zIndex,
paddingTop, paddingRight, paddingBottom, paddingLeft, boxSizing,
width, height, autoMargins,
marginTop,
marginRight,
marginBottom,
marginLeft,
borderTopWidth,
borderRightWidth,
borderBottomWidth,
borderLeftWidth,
paddingTop,
paddingRight,
paddingBottom,
paddingLeft,
width,
height,
} = rx.recv().unwrap().ok_or(())?; } = rx.recv().unwrap().ok_or(())?;
let auto_margins = msg.get("autoMargins") let auto_margins = msg
.and_then(&Value::as_bool).unwrap_or(false); .get("autoMargins")
.and_then(&Value::as_bool)
.unwrap_or(false);
// http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/styles.js // http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/styles.js
let msg = GetLayoutReply { let msg = GetLayoutReply {
@ -504,10 +536,18 @@ impl Actor for PageStyleActor {
autoMargins: if auto_margins { autoMargins: if auto_margins {
let mut m = Map::new(); let mut m = Map::new();
let auto = serde_json::value::Value::String("auto".to_owned()); let auto = serde_json::value::Value::String("auto".to_owned());
if autoMargins.top { m.insert("top".to_owned(), auto.clone()); } if autoMargins.top {
if autoMargins.right { m.insert("right".to_owned(), auto.clone()); } m.insert("top".to_owned(), auto.clone());
if autoMargins.bottom { m.insert("bottom".to_owned(), auto.clone()); } }
if autoMargins.left { m.insert("left".to_owned(), auto.clone()); } if autoMargins.right {
m.insert("right".to_owned(), auto.clone());
}
if autoMargins.bottom {
m.insert("bottom".to_owned(), auto.clone());
}
if autoMargins.left {
m.insert("left".to_owned(), auto.clone());
}
serde_json::value::Value::Object(m) serde_json::value::Value::Object(m)
} else { } else {
serde_json::value::Value::Null serde_json::value::Value::Null
@ -531,7 +571,7 @@ impl Actor for PageStyleActor {
let msg = serde_json::from_str::<Value>(&msg).unwrap(); let msg = serde_json::from_str::<Value>(&msg).unwrap();
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })
@ -543,11 +583,13 @@ impl Actor for InspectorActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"getWalker" => { "getWalker" => {
if self.walker.borrow().is_none() { if self.walker.borrow().is_none() {
@ -562,21 +604,24 @@ impl Actor for InspectorActor {
} }
let (tx, rx) = ipc::channel().unwrap(); let (tx, rx) = ipc::channel().unwrap();
self.script_chan.send(GetRootNode(self.pipeline, tx)).unwrap(); self.script_chan
.send(GetRootNode(self.pipeline, tx))
.unwrap();
let root_info = rx.recv().unwrap().ok_or(())?; let root_info = rx.recv().unwrap().ok_or(())?;
let node = root_info.encode(registry, false, self.script_chan.clone(), self.pipeline); let node =
root_info.encode(registry, false, self.script_chan.clone(), self.pipeline);
let msg = GetWalkerReply { let msg = GetWalkerReply {
from: self.name(), from: self.name(),
walker: WalkerMsg { walker: WalkerMsg {
actor: self.walker.borrow().clone().unwrap(), actor: self.walker.borrow().clone().unwrap(),
root: node, root: node,
} },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getPageStyle" => { "getPageStyle" => {
if self.pageStyle.borrow().is_none() { if self.pageStyle.borrow().is_none() {
@ -598,7 +643,7 @@ impl Actor for InspectorActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
//TODO: this is an old message; try adding highlightable to the root traits instead //TODO: this is an old message; try adding highlightable to the root traits instead
// and support getHighlighter instead // and support getHighlighter instead
@ -621,7 +666,7 @@ impl Actor for InspectorActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })

View file

@ -28,11 +28,13 @@ impl Actor for MemoryActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_registry: &ActorRegistry, &self,
_msg_type: &str, _registry: &ActorRegistry,
_msg: &Map<String, Value>, _msg_type: &str,
_stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
_stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Ignored) Ok(ActorMessageStatus::Ignored)
} }
} }
@ -42,7 +44,7 @@ impl MemoryActor {
pub fn create(registry: &ActorRegistry) -> String { pub fn create(registry: &ActorRegistry) -> String {
let actor_name = registry.new_name("memory"); let actor_name = registry.new_name("memory");
let actor = MemoryActor { let actor = MemoryActor {
name: actor_name.clone() name: actor_name.clone(),
}; };
registry.register_later(Box::new(actor)); registry.register_later(Box::new(actor));

View file

@ -34,7 +34,7 @@ struct HttpRequest {
struct HttpResponse { struct HttpResponse {
headers: Option<Headers>, headers: Option<Headers>,
status: Option<RawStatus>, status: Option<RawStatus>,
body: Option<Vec<u8>> body: Option<Vec<u8>>,
} }
pub struct NetworkEventActor { pub struct NetworkEventActor {
@ -52,7 +52,7 @@ pub struct EventActor {
pub startedDateTime: String, pub startedDateTime: String,
pub timeStamp: i64, pub timeStamp: i64,
pub isXHR: bool, pub isXHR: bool,
pub private: bool pub private: bool,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -79,14 +79,12 @@ pub struct ResponseContentMsg {
pub discardResponseBody: bool, pub discardResponseBody: bool,
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct ResponseHeadersMsg { pub struct ResponseHeadersMsg {
pub headers: usize, pub headers: usize,
pub headersSize: usize, pub headersSize: usize,
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct RequestCookiesMsg { pub struct RequestCookiesMsg {
pub cookies: usize, pub cookies: usize,
@ -103,7 +101,7 @@ struct GetRequestHeadersReply {
from: String, from: String,
headers: Vec<Header>, headers: Vec<Header>,
headerSize: usize, headerSize: usize,
rawHeaders: String rawHeaders: String,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -117,7 +115,7 @@ struct GetResponseHeadersReply {
from: String, from: String,
headers: Vec<Header>, headers: Vec<Header>,
headerSize: usize, headerSize: usize,
rawHeaders: String rawHeaders: String,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -131,19 +129,19 @@ struct GetResponseContentReply {
struct GetRequestPostDataReply { struct GetRequestPostDataReply {
from: String, from: String,
postData: Option<Vec<u8>>, postData: Option<Vec<u8>>,
postDataDiscarded: bool postDataDiscarded: bool,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct GetRequestCookiesReply { struct GetRequestCookiesReply {
from: String, from: String,
cookies: Vec<u8> cookies: Vec<u8>,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct GetResponseCookiesReply { struct GetResponseCookiesReply {
from: String, from: String,
cookies: Vec<u8> cookies: Vec<u8>,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -179,11 +177,13 @@ impl Actor for NetworkEventActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_registry: &ActorRegistry, &self,
msg_type: &str, _registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"getRequestHeaders" => { "getRequestHeaders" => {
let mut headers = Vec::new(); let mut headers = Vec::new();
@ -194,7 +194,10 @@ impl Actor for NetworkEventActor {
let value = item.value_string(); let value = item.value_string();
rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n"; rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n";
headersSize += name.len() + value.len(); headersSize += name.len() + value.len();
headers.push(Header { name: name.to_owned(), value: value.to_owned() }); headers.push(Header {
name: name.to_owned(),
value: value.to_owned(),
});
} }
let msg = GetRequestHeadersReply { let msg = GetRequestHeadersReply {
from: self.name(), from: self.name(),
@ -204,7 +207,7 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getRequestCookies" => { "getRequestCookies" => {
let mut cookies = Vec::new(); let mut cookies = Vec::new();
if let Some(req_cookies) = self.request.headers.get_raw("Cookie") { if let Some(req_cookies) = self.request.headers.get_raw("Cookie") {
@ -221,7 +224,7 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getRequestPostData" => { "getRequestPostData" => {
let msg = GetRequestPostDataReply { let msg = GetRequestPostDataReply {
from: self.name(), from: self.name(),
@ -230,7 +233,7 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getResponseHeaders" => { "getResponseHeaders" => {
if let Some(ref response_headers) = self.response.headers { if let Some(ref response_headers) = self.response.headers {
let mut headers = vec![]; let mut headers = vec![];
@ -258,7 +261,7 @@ impl Actor for NetworkEventActor {
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
} }
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getResponseCookies" => { "getResponseCookies" => {
let mut cookies = Vec::new(); let mut cookies = Vec::new();
if let Some(res_cookies) = self.request.headers.get_raw("set-cookie") { if let Some(res_cookies) = self.request.headers.get_raw("set-cookie") {
@ -275,7 +278,7 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getResponseContent" => { "getResponseContent" => {
let msg = GetResponseContentReply { let msg = GetResponseContentReply {
from: self.name(), from: self.name(),
@ -284,7 +287,7 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getEventTimings" => { "getEventTimings" => {
// TODO: This is a fake timings msg // TODO: This is a fake timings msg
let timingsObj = Timings { let timingsObj = Timings {
@ -304,19 +307,19 @@ impl Actor for NetworkEventActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"getSecurityInfo" => { "getSecurityInfo" => {
// TODO: Send the correct values for securityInfo. // TODO: Send the correct values for securityInfo.
let msg = GetSecurityInfoReply { let msg = GetSecurityInfoReply {
from: self.name(), from: self.name(),
securityInfo: SecurityInfo { securityInfo: SecurityInfo {
state: "insecure".to_owned() state: "insecure".to_owned(),
}, },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored _ => ActorMessageStatus::Ignored,
}) })
} }
} }
@ -382,8 +385,13 @@ impl NetworkEventActor {
// TODO: Send the correct values for all these fields. // TODO: Send the correct values for all these fields.
let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len()); let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len());
let hSize = hSizeOption.unwrap_or(0); let hSize = hSizeOption.unwrap_or(0);
let (status_code, status_message) = self.response.status.as_ref(). let (status_code, status_message) = self
map_or((0, "".to_owned()), |&RawStatus(ref code, ref text)| (*code, text.clone().into_owned())); .response
.status
.as_ref()
.map_or((0, "".to_owned()), |&RawStatus(ref code, ref text)| {
(*code, text.clone().into_owned())
});
// TODO: Send the correct values for remoteAddress and remotePort and http_version. // TODO: Send the correct values for remoteAddress and remotePort and http_version.
ResponseStartMsg { ResponseStartMsg {
httpVersion: "HTTP/1.1".to_owned(), httpVersion: "HTTP/1.1".to_owned(),
@ -392,7 +400,7 @@ impl NetworkEventActor {
status: status_code.to_string(), status: status_code.to_string(),
statusText: status_message, statusText: status_message,
headersSize: hSize, headersSize: hSize,
discardResponseBody: false discardResponseBody: false,
} }
} }
@ -401,7 +409,7 @@ impl NetworkEventActor {
if let Some(ref headers) = self.response.headers { if let Some(ref headers) = self.response.headers {
mString = match headers.get() { mString = match headers.get() {
Some(&ContentType(ref mime)) => mime.to_string(), Some(&ContentType(ref mime)) => mime.to_string(),
None => "".to_owned() None => "".to_owned(),
}; };
} }
// TODO: Set correct values when response's body is sent to the devtools in http_loader. // TODO: Set correct values when response's body is sent to the devtools in http_loader.
@ -418,7 +426,7 @@ impl NetworkEventActor {
if let Some(ref headers) = self.response.headers { if let Some(ref headers) = self.response.headers {
cookies_size = match headers.get() { cookies_size = match headers.get() {
Some(&Cookie(ref cookie)) => cookie.len(), Some(&Cookie(ref cookie)) => cookie.len(),
None => 0 None => 0,
}; };
} }
ResponseCookiesMsg { ResponseCookiesMsg {
@ -431,10 +439,9 @@ impl NetworkEventActor {
let mut headers_byte_count = 0; let mut headers_byte_count = 0;
if let Some(ref headers) = self.response.headers { if let Some(ref headers) = self.response.headers {
headers_size = headers.len(); headers_size = headers.len();
for item in headers.iter() { for item in headers.iter() {
headers_byte_count += item.name().len() + item.value_string().len(); headers_byte_count += item.name().len() + item.value_string().len();
} }
} }
ResponseHeadersMsg { ResponseHeadersMsg {
headers: headers_size, headers: headers_size,
@ -443,10 +450,11 @@ impl NetworkEventActor {
} }
pub fn request_headers(&self) -> RequestHeadersMsg { pub fn request_headers(&self) -> RequestHeadersMsg {
let size = self.request let size = self
.headers .request
.iter() .headers
.fold(0, |acc, h| acc + h.name().len() + h.value_string().len()); .iter()
.fold(0, |acc, h| acc + h.name().len() + h.value_string().len());
RequestHeadersMsg { RequestHeadersMsg {
headers: self.request.headers.len(), headers: self.request.headers.len(),
headersSize: size, headersSize: size,
@ -456,7 +464,7 @@ impl NetworkEventActor {
pub fn request_cookies(&self) -> RequestCookiesMsg { pub fn request_cookies(&self) -> RequestCookiesMsg {
let cookies_size = match self.request.headers.get() { let cookies_size = match self.request.headers.get() {
Some(&Cookie(ref cookie)) => cookie.len(), Some(&Cookie(ref cookie)) => cookie.len(),
None => 0 None => 0,
}; };
RequestCookiesMsg { RequestCookiesMsg {
cookies: cookies_size, cookies: cookies_size,

View file

@ -15,11 +15,13 @@ impl Actor for ObjectActor {
fn name(&self) -> String { fn name(&self) -> String {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_: &ActorRegistry, &self,
_: &str, _: &ActorRegistry,
_: &Map<String, Value>, _: &str,
_: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _: &Map<String, Value>,
_: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Ignored) Ok(ActorMessageStatus::Ignored)
} }
} }

View file

@ -51,11 +51,13 @@ impl Actor for PerformanceActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_registry: &ActorRegistry, &self,
msg_type: &str, _registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"connect" => { "connect" => {
let msg = ConnectReply { let msg = ConnectReply {
@ -79,11 +81,11 @@ impl Actor for PerformanceActor {
value: SuccessMsg { value: SuccessMsg {
success: true, success: true,
errors: vec![], errors: vec![],
} },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })
} }
@ -91,28 +93,34 @@ impl Actor for PerformanceActor {
impl PerformanceActor { impl PerformanceActor {
pub fn new(name: String) -> PerformanceActor { pub fn new(name: String) -> PerformanceActor {
PerformanceActor { PerformanceActor { name: name }
name: name,
}
} }
pub fn description() -> ActorDescription { pub fn description() -> ActorDescription {
ActorDescription { ActorDescription {
category: "actor", category: "actor",
typeName: "performance", typeName: "performance",
methods: vec![ methods: vec![Method {
Method { name: "canCurrentlyRecord",
name: "canCurrentlyRecord", request: Value::Object(
request: Value::Object(vec![ vec![(
("type".to_owned(), Value::String("canCurrentlyRecord".to_owned())), "type".to_owned(),
].into_iter().collect()), Value::String("canCurrentlyRecord".to_owned()),
response: Value::Object(vec![ )].into_iter()
("value".to_owned(), Value::Object(vec![ .collect(),
("_retval".to_owned(), Value::String("json".to_owned())), ),
].into_iter().collect())), response: Value::Object(
].into_iter().collect()), vec![(
}, "value".to_owned(),
], Value::Object(
vec![("_retval".to_owned(), Value::String("json".to_owned()))]
.into_iter()
.collect(),
),
)].into_iter()
.collect(),
),
}],
} }
} }
} }

View file

@ -15,19 +15,19 @@ impl Actor for ProfilerActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_registry: &ActorRegistry, &self,
_msg_type: &str, _registry: &ActorRegistry,
_msg: &Map<String, Value>, _msg_type: &str,
_stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
_stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Ignored) Ok(ActorMessageStatus::Ignored)
} }
} }
impl ProfilerActor { impl ProfilerActor {
pub fn new(name: String) -> ProfilerActor { pub fn new(name: String) -> ProfilerActor {
ProfilerActor { ProfilerActor { name: name }
name: name,
}
} }
} }

View file

@ -6,7 +6,6 @@
/// (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/root.js). /// (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/root.js).
/// Connection point for all new remote devtools interactions, providing lists of know actors /// Connection point for all new remote devtools interactions, providing lists of know actors
/// that perform more specific actions (tabs, addons, browser chrome, etc.) /// that perform more specific actions (tabs, addons, browser chrome, etc.)
use actor::{Actor, ActorMessageStatus, ActorRegistry}; use actor::{Actor, ActorMessageStatus, ActorRegistry};
use actors::performance::PerformanceActor; use actors::performance::PerformanceActor;
use actors::tab::{TabActor, TabActorMsg}; use actors::tab::{TabActor, TabActorMsg};
@ -65,11 +64,13 @@ impl Actor for RootActor {
"root".to_owned() "root".to_owned()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"listAddons" => { "listAddons" => {
let actor = ListAddonsReply { let actor = ListAddonsReply {
@ -78,20 +79,22 @@ impl Actor for RootActor {
}; };
stream.write_json_packet(&actor); stream.write_json_packet(&actor);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
//https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs //https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs
"listTabs" => { "listTabs" => {
let actor = ListTabsReply { let actor = ListTabsReply {
from: "root".to_owned(), from: "root".to_owned(),
selected: 0, selected: 0,
tabs: self.tabs.iter().map(|tab| { tabs: self
registry.find::<TabActor>(tab).encodable() .tabs
}).collect() .iter()
.map(|tab| registry.find::<TabActor>(tab).encodable())
.collect(),
}; };
stream.write_json_packet(&actor); stream.write_json_packet(&actor);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"protocolDescription" => { "protocolDescription" => {
let msg = ProtocolDescriptionReply { let msg = ProtocolDescriptionReply {
@ -102,9 +105,9 @@ impl Actor for RootActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored _ => ActorMessageStatus::Ignored,
}) })
} }
} }
@ -118,7 +121,7 @@ impl RootActor {
sources: true, sources: true,
highlightable: true, highlightable: true,
customHighlighters: true, customHighlighters: true,
networkMonitor: true networkMonitor: true,
}, },
} }
} }

View file

@ -37,7 +37,7 @@ struct TabDetachedReply {
#[derive(Serialize)] #[derive(Serialize)]
struct ReconfigureReply { struct ReconfigureReply {
from: String from: String,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -84,25 +84,28 @@ impl Actor for TabActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"reconfigure" => { "reconfigure" => {
if let Some(options) = msg.get("options").and_then(|o| o.as_object()) { if let Some(options) = msg.get("options").and_then(|o| o.as_object()) {
if let Some(val) = options.get("performReload") { if let Some(val) = options.get("performReload") {
if val.as_bool().unwrap_or(false) { if val.as_bool().unwrap_or(false) {
let console_actor = registry.find::<ConsoleActor>(&self.console); let console_actor = registry.find::<ConsoleActor>(&self.console);
let _ = console_actor.script_chan.send( let _ = console_actor
DevtoolScriptControlMsg::Reload(console_actor.pipeline)); .script_chan
.send(DevtoolScriptControlMsg::Reload(console_actor.pipeline));
} }
} }
} }
stream.write_json_packet(&ReconfigureReply { from: self.name() }); stream.write_json_packet(&ReconfigureReply { from: self.name() });
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
// https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs // https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs
// (see "To attach to a _tabActor_") // (see "To attach to a _tabActor_")
@ -116,12 +119,17 @@ impl Actor for TabActor {
traits: TabTraits, traits: TabTraits,
}; };
let console_actor = registry.find::<ConsoleActor>(&self.console); let console_actor = registry.find::<ConsoleActor>(&self.console);
console_actor.streams.borrow_mut().push(stream.try_clone().unwrap()); console_actor
.streams
.borrow_mut()
.push(stream.try_clone().unwrap());
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
console_actor.script_chan.send( console_actor
WantsLiveNotifications(console_actor.pipeline, true)).unwrap(); .script_chan
.send(WantsLiveNotifications(console_actor.pipeline, true))
.unwrap();
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
//FIXME: The current implementation won't work for multiple connections. Need to ensure 105 //FIXME: The current implementation won't work for multiple connections. Need to ensure 105
// that the correct stream is removed. // that the correct stream is removed.
@ -133,21 +141,23 @@ impl Actor for TabActor {
let console_actor = registry.find::<ConsoleActor>(&self.console); let console_actor = registry.find::<ConsoleActor>(&self.console);
console_actor.streams.borrow_mut().pop(); console_actor.streams.borrow_mut().pop();
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
console_actor.script_chan.send( console_actor
WantsLiveNotifications(console_actor.pipeline, false)).unwrap(); .script_chan
.send(WantsLiveNotifications(console_actor.pipeline, false))
.unwrap();
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"listFrames" => { "listFrames" => {
let msg = ListFramesReply { let msg = ListFramesReply {
from: self.name(), from: self.name(),
frames: vec!(), frames: vec![],
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored _ => ActorMessageStatus::Ignored,
}) })
} }
} }

View file

@ -35,7 +35,7 @@ struct ThreadResumedReply {
#[derive(Serialize)] #[derive(Serialize)]
struct ReconfigureReply { struct ReconfigureReply {
from: String from: String,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -53,9 +53,7 @@ pub struct ThreadActor {
impl ThreadActor { impl ThreadActor {
pub fn new(name: String) -> ThreadActor { pub fn new(name: String) -> ThreadActor {
ThreadActor { ThreadActor { name: name }
name: name,
}
} }
} }
@ -64,11 +62,13 @@ impl Actor for ThreadActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
_msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"attach" => { "attach" => {
let msg = ThreadAttachedReply { let msg = ThreadAttachedReply {
@ -76,7 +76,9 @@ impl Actor for ThreadActor {
type_: "paused".to_owned(), type_: "paused".to_owned(),
actor: registry.new_name("pause"), actor: registry.new_name("pause"),
poppedFrames: vec![], poppedFrames: vec![],
why: WhyMsg { type_: "attached".to_owned() }, why: WhyMsg {
type_: "attached".to_owned(),
},
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
@ -94,7 +96,7 @@ impl Actor for ThreadActor {
"reconfigure" => { "reconfigure" => {
stream.write_json_packet(&ReconfigureReply { from: self.name() }); stream.write_json_packet(&ReconfigureReply { from: self.name() });
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"sources" => { "sources" => {
let msg = SourcesReply { let msg = SourcesReply {
@ -103,7 +105,7 @@ impl Actor for ThreadActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => ActorMessageStatus::Ignored, _ => ActorMessageStatus::Ignored,
}) })

View file

@ -44,7 +44,7 @@ struct Emitter {
#[derive(Serialize)] #[derive(Serialize)]
struct IsRecordingReply { struct IsRecordingReply {
from: String, from: String,
value: bool value: bool,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -103,8 +103,10 @@ pub struct HighResolutionStamp(f64);
impl HighResolutionStamp { impl HighResolutionStamp {
pub fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp { pub fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp {
let duration = start_stamp.to(time).num_microseconds() let duration = start_stamp
.expect("Too big duration in microseconds"); .to(time)
.num_microseconds()
.expect("Too big duration in microseconds");
HighResolutionStamp(duration as f64 / 1000 as f64) HighResolutionStamp(duration as f64 / 1000 as f64)
} }
@ -122,11 +124,12 @@ impl Serialize for HighResolutionStamp {
static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u64 = 200; //ms static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u64 = 200; //ms
impl TimelineActor { impl TimelineActor {
pub fn new(name: String, pub fn new(
pipeline: PipelineId, name: String,
script_sender: IpcSender<DevtoolScriptControlMsg>) -> TimelineActor { pipeline: PipelineId,
let marker_types = vec!(TimelineMarkerType::Reflow, script_sender: IpcSender<DevtoolScriptControlMsg>,
TimelineMarkerType::DOMEvent); ) -> TimelineActor {
let marker_types = vec![TimelineMarkerType::Reflow, TimelineMarkerType::DOMEvent];
TimelineActor { TimelineActor {
name: name, name: name,
@ -141,15 +144,20 @@ impl TimelineActor {
} }
} }
fn pull_timeline_data(&self, receiver: IpcReceiver<Option<TimelineMarker>>, mut emitter: Emitter) { fn pull_timeline_data(
&self,
receiver: IpcReceiver<Option<TimelineMarker>>,
mut emitter: Emitter,
) {
let is_recording = self.is_recording.clone(); let is_recording = self.is_recording.clone();
if !*is_recording.lock().unwrap() { if !*is_recording.lock().unwrap() {
return; return;
} }
thread::Builder::new().name("PullTimelineMarkers".to_owned()).spawn(move || { thread::Builder::new()
loop { .name("PullTimelineMarkers".to_owned())
.spawn(move || loop {
if !*is_recording.lock().unwrap() { if !*is_recording.lock().unwrap() {
break; break;
} }
@ -161,8 +169,7 @@ impl TimelineActor {
emitter.send(markers); emitter.send(markers);
thread::sleep(Duration::from_millis(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT)); thread::sleep(Duration::from_millis(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT));
} }).expect("Thread spawning failed");
}).expect("Thread spawning failed");
} }
} }
@ -171,19 +178,24 @@ impl Actor for TimelineActor {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
registry: &ActorRegistry, &self,
msg_type: &str, registry: &ActorRegistry,
msg: &Map<String, Value>, msg_type: &str,
stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> { msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"start" => { "start" => {
**self.is_recording.lock().as_mut().unwrap() = true; **self.is_recording.lock().as_mut().unwrap() = true;
let (tx, rx) = ipc::channel::<Option<TimelineMarker>>().unwrap(); let (tx, rx) = ipc::channel::<Option<TimelineMarker>>().unwrap();
self.script_sender.send(SetTimelineMarkers(self.pipeline, self.script_sender
self.marker_types.clone(), .send(SetTimelineMarkers(
tx)).unwrap(); self.pipeline,
self.marker_types.clone(),
tx,
)).unwrap();
*self.stream.borrow_mut() = stream.try_clone().ok(); *self.stream.borrow_mut() = stream.try_clone().ok();
@ -198,18 +210,22 @@ impl Actor for TimelineActor {
if let Some(with_ticks) = msg.get("withTicks") { if let Some(with_ticks) = msg.get("withTicks") {
if let Some(true) = with_ticks.as_bool() { if let Some(true) = with_ticks.as_bool() {
let framerate_actor = Some(FramerateActor::create( let framerate_actor = Some(FramerateActor::create(
registry, registry,
self.pipeline.clone(), self.pipeline.clone(),
self.script_sender.clone())); self.script_sender.clone(),
));
*self.framerate_actor.borrow_mut() = framerate_actor; *self.framerate_actor.borrow_mut() = framerate_actor;
} }
} }
let emitter = Emitter::new(self.name(), registry.shareable(), let emitter = Emitter::new(
registry.start_stamp(), self.name(),
stream.try_clone().unwrap(), registry.shareable(),
self.memory_actor.borrow().clone(), registry.start_stamp(),
self.framerate_actor.borrow().clone()); stream.try_clone().unwrap(),
self.memory_actor.borrow().clone(),
self.framerate_actor.borrow().clone(),
);
self.pull_timeline_data(rx, emitter); self.pull_timeline_data(rx, emitter);
@ -219,7 +235,7 @@ impl Actor for TimelineActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"stop" => { "stop" => {
let msg = StopReply { let msg = StopReply {
@ -228,7 +244,11 @@ impl Actor for TimelineActor {
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
self.script_sender.send(DropTimelineMarkers(self.pipeline, self.marker_types.clone())).unwrap(); self.script_sender
.send(DropTimelineMarkers(
self.pipeline,
self.marker_types.clone(),
)).unwrap();
if let Some(ref actor_name) = *self.framerate_actor.borrow() { if let Some(ref actor_name) = *self.framerate_actor.borrow() {
registry.drop_actor_later(actor_name.clone()); registry.drop_actor_later(actor_name.clone());
@ -241,32 +261,32 @@ impl Actor for TimelineActor {
**self.is_recording.lock().as_mut().unwrap() = false; **self.is_recording.lock().as_mut().unwrap() = false;
self.stream.borrow_mut().take(); self.stream.borrow_mut().take();
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
"isRecording" => { "isRecording" => {
let msg = IsRecordingReply { let msg = IsRecordingReply {
from: self.name(), from: self.name(),
value: self.is_recording.lock().unwrap().clone() value: self.is_recording.lock().unwrap().clone(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
} },
_ => { _ => ActorMessageStatus::Ignored,
ActorMessageStatus::Ignored
}
}) })
} }
} }
impl Emitter { impl Emitter {
pub fn new(name: String, pub fn new(
registry: Arc<Mutex<ActorRegistry>>, name: String,
start_stamp: PreciseTime, registry: Arc<Mutex<ActorRegistry>>,
stream: TcpStream, start_stamp: PreciseTime,
memory_actor_name: Option<String>, stream: TcpStream,
framerate_actor_name: Option<String>) -> Emitter { memory_actor_name: Option<String>,
framerate_actor_name: Option<String>,
) -> Emitter {
Emitter { Emitter {
from: name, from: name,
stream: stream, stream: stream,

View file

@ -17,11 +17,13 @@ impl Actor for WorkerActor {
fn name(&self) -> String { fn name(&self) -> String {
self.name.clone() self.name.clone()
} }
fn handle_message(&self, fn handle_message(
_: &ActorRegistry, &self,
_: &str, _: &ActorRegistry,
_: &Map<String, Value>, _: &str,
_: &mut TcpStream) -> Result<ActorMessageStatus, ()> { _: &Map<String, Value>,
_: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Processed) Ok(ActorMessageStatus::Processed)
} }
} }

View file

@ -9,7 +9,6 @@
#![crate_name = "devtools"] #![crate_name = "devtools"]
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
@ -19,7 +18,8 @@ extern crate ipc_channel;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate msg; extern crate msg;
#[macro_use] extern crate serde; #[macro_use]
extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate time; extern crate time;
@ -128,23 +128,24 @@ pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
let (sender, receiver) = channel(); let (sender, receiver) = channel();
{ {
let sender = sender.clone(); let sender = sender.clone();
thread::Builder::new().name("Devtools".to_owned()).spawn(move || { thread::Builder::new()
run_server(sender, receiver, port) .name("Devtools".to_owned())
}).expect("Thread spawning failed"); .spawn(move || run_server(sender, receiver, port))
.expect("Thread spawning failed");
} }
sender sender
} }
fn run_server(sender: Sender<DevtoolsControlMsg>, fn run_server(
receiver: Receiver<DevtoolsControlMsg>, sender: Sender<DevtoolsControlMsg>,
port: u16) { receiver: Receiver<DevtoolsControlMsg>,
port: u16,
) {
let listener = TcpListener::bind(&("127.0.0.1", port)).unwrap(); let listener = TcpListener::bind(&("127.0.0.1", port)).unwrap();
let mut registry = ActorRegistry::new(); let mut registry = ActorRegistry::new();
let root = Box::new(RootActor { let root = Box::new(RootActor { tabs: vec![] });
tabs: vec!(),
});
registry.register(root); registry.register(root);
registry.find::<RootActor>("root"); registry.find::<RootActor>("root");
@ -158,7 +159,6 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new();
/// Process the input from a single devtools client until EOF. /// Process the input from a single devtools client until EOF.
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) { fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
debug!("connection established to {}", stream.peer_addr().unwrap()); debug!("connection established to {}", stream.peer_addr().unwrap());
@ -171,21 +171,24 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
'outer: loop { 'outer: loop {
match stream.read_json_packet() { match stream.read_json_packet() {
Ok(Some(json_packet)) => { Ok(Some(json_packet)) => {
if let Err(()) = actors.lock().unwrap().handle_message(json_packet.as_object().unwrap(), if let Err(()) = actors
&mut stream) { .lock()
.unwrap()
.handle_message(json_packet.as_object().unwrap(), &mut stream)
{
debug!("error: devtools actor stopped responding"); debug!("error: devtools actor stopped responding");
let _ = stream.shutdown(Shutdown::Both); let _ = stream.shutdown(Shutdown::Both);
break 'outer break 'outer;
} }
} },
Ok(None) => { Ok(None) => {
debug!("error: EOF"); debug!("error: EOF");
break 'outer break 'outer;
} },
Err(err_msg) => { Err(err_msg) => {
debug!("error: {}", err_msg); debug!("error: {}", err_msg);
break 'outer break 'outer;
} },
} }
} }
} }
@ -199,12 +202,14 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
// We need separate actor representations for each script global that exists; // We need separate actor representations for each script global that exists;
// clients can theoretically connect to multiple globals simultaneously. // clients can theoretically connect to multiple globals simultaneously.
// TODO: move this into the root or tab modules? // TODO: move this into the root or tab modules?
fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>, fn handle_new_global(
ids: (PipelineId, Option<WorkerId>), actors: Arc<Mutex<ActorRegistry>>,
script_sender: IpcSender<DevtoolScriptControlMsg>, ids: (PipelineId, Option<WorkerId>),
actor_pipelines: &mut HashMap<PipelineId, String>, script_sender: IpcSender<DevtoolScriptControlMsg>,
actor_workers: &mut HashMap<(PipelineId, WorkerId), String>, actor_pipelines: &mut HashMap<PipelineId, String>,
page_info: DevtoolsPageInfo) { actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
page_info: DevtoolsPageInfo,
) {
let mut actors = actors.lock().unwrap(); let mut actors = actors.lock().unwrap();
let (pipeline, worker_id) = ids; let (pipeline, worker_id) = ids;
@ -226,9 +231,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
pipeline: pipeline, pipeline: pipeline,
}; };
let timeline = TimelineActor::new(actors.new_name("timeline"), let timeline = TimelineActor::new(actors.new_name("timeline"), pipeline, script_sender);
pipeline,
script_sender);
let profiler = ProfilerActor::new(actors.new_name("profiler")); let profiler = ProfilerActor::new(actors.new_name("profiler"));
let performance = PerformanceActor::new(actors.new_name("performance")); let performance = PerformanceActor::new(actors.new_name("performance"));
@ -251,7 +254,15 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
let root = actors.find_mut::<RootActor>("root"); let root = actors.find_mut::<RootActor>("root");
root.tabs.push(tab.name.clone()); root.tabs.push(tab.name.clone());
(tab, console, inspector, timeline, profiler, performance, thread) (
tab,
console,
inspector,
timeline,
profiler,
performance,
thread,
)
}; };
if let Some(id) = worker_id { if let Some(id) = worker_id {
@ -274,14 +285,21 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
actors.register(Box::new(thread)); actors.register(Box::new(thread));
} }
fn handle_console_message(actors: Arc<Mutex<ActorRegistry>>, fn handle_console_message(
id: PipelineId, actors: Arc<Mutex<ActorRegistry>>,
worker_id: Option<WorkerId>, id: PipelineId,
console_message: ConsoleMessage, worker_id: Option<WorkerId>,
actor_pipelines: &HashMap<PipelineId, String>, console_message: ConsoleMessage,
actor_workers: &HashMap<(PipelineId, WorkerId), String>) { actor_pipelines: &HashMap<PipelineId, String>,
let console_actor_name = match find_console_actor(actors.clone(), id, worker_id, actor_workers, actor_workers: &HashMap<(PipelineId, WorkerId), String>,
actor_pipelines) { ) {
let console_actor_name = match find_console_actor(
actors.clone(),
id,
worker_id,
actor_workers,
actor_pipelines,
) {
Some(name) => name, Some(name) => name,
None => return, None => return,
}; };
@ -296,10 +314,10 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
LogLevel::Info => "info", LogLevel::Info => "info",
LogLevel::Warn => "warn", LogLevel::Warn => "warn",
LogLevel::Error => "error", LogLevel::Error => "error",
_ => "log" _ => "log",
}.to_owned(), }.to_owned(),
timeStamp: precise_time_ns(), timeStamp: precise_time_ns(),
arguments: vec!(console_message.message), arguments: vec![console_message.message],
filename: console_message.filename, filename: console_message.filename,
lineNumber: console_message.lineNumber, lineNumber: console_message.lineNumber,
columnNumber: console_message.columnNumber, columnNumber: console_message.columnNumber,
@ -310,11 +328,13 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
} }
} }
fn find_console_actor(actors: Arc<Mutex<ActorRegistry>>, fn find_console_actor(
id: PipelineId, actors: Arc<Mutex<ActorRegistry>>,
worker_id: Option<WorkerId>, id: PipelineId,
actor_workers: &HashMap<(PipelineId, WorkerId), String>, worker_id: Option<WorkerId>,
actor_pipelines: &HashMap<PipelineId, String>) -> Option<String> { actor_workers: &HashMap<(PipelineId, WorkerId), String>,
actor_pipelines: &HashMap<PipelineId, String>,
) -> Option<String> {
let actors = actors.lock().unwrap(); let actors = actors.lock().unwrap();
if let Some(worker_id) = worker_id { if let Some(worker_id) = worker_id {
let actor_name = (*actor_workers).get(&(id, worker_id))?; let actor_name = (*actor_workers).get(&(id, worker_id))?;
@ -325,20 +345,28 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
} }
} }
fn handle_network_event(actors: Arc<Mutex<ActorRegistry>>, fn handle_network_event(
mut connections: Vec<TcpStream>, actors: Arc<Mutex<ActorRegistry>>,
actor_pipelines: &HashMap<PipelineId, String>, mut connections: Vec<TcpStream>,
actor_requests: &mut HashMap<String, String>, actor_pipelines: &HashMap<PipelineId, String>,
actor_workers: &HashMap<(PipelineId, WorkerId), String>, actor_requests: &mut HashMap<String, String>,
pipeline_id: PipelineId, actor_workers: &HashMap<(PipelineId, WorkerId), String>,
request_id: String, pipeline_id: PipelineId,
network_event: NetworkEvent) { request_id: String,
let console_actor_name = match find_console_actor(actors.clone(), pipeline_id, None, network_event: NetworkEvent,
actor_workers, actor_pipelines) { ) {
let console_actor_name = match find_console_actor(
actors.clone(),
pipeline_id,
None,
actor_workers,
actor_pipelines,
) {
Some(name) => name, Some(name) => name,
None => return, None => return,
}; };
let netevent_actor_name = find_network_event_actor(actors.clone(), actor_requests, request_id.clone()); let netevent_actor_name =
find_network_event_actor(actors.clone(), actor_requests, request_id.clone());
let mut actors = actors.lock().unwrap(); let mut actors = actors.lock().unwrap();
let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name); let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name);
@ -356,8 +384,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
for stream in &mut connections { for stream in &mut connections {
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
} }
},
}
NetworkEvent::HttpResponse(httpresponse) => { NetworkEvent::HttpResponse(httpresponse) => {
//Store the response information in the actor //Store the response information in the actor
actor.add_response(httpresponse); actor.add_response(httpresponse);
@ -385,7 +412,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
from: netevent_actor_name.clone(), from: netevent_actor_name.clone(),
type_: "networkEventUpdate".to_owned(), type_: "networkEventUpdate".to_owned(),
updateType: "responseStart".to_owned(), updateType: "responseStart".to_owned(),
response: actor.response_start() response: actor.response_start(),
}; };
for stream in &mut connections { for stream in &mut connections {
@ -441,78 +468,109 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
for stream in &mut connections { for stream in &mut connections {
stream.write_merged_json_packet(&msg, &actor.response_headers()); stream.write_merged_json_packet(&msg, &actor.response_headers());
} }
} },
} }
} }
// Find the name of NetworkEventActor corresponding to request_id // Find the name of NetworkEventActor corresponding to request_id
// Create a new one if it does not exist, add it to the actor_requests hashmap // Create a new one if it does not exist, add it to the actor_requests hashmap
fn find_network_event_actor(actors: Arc<Mutex<ActorRegistry>>, fn find_network_event_actor(
actor_requests: &mut HashMap<String, String>, actors: Arc<Mutex<ActorRegistry>>,
request_id: String) -> String { actor_requests: &mut HashMap<String, String>,
request_id: String,
) -> String {
let mut actors = actors.lock().unwrap(); let mut actors = actors.lock().unwrap();
match (*actor_requests).entry(request_id) { match (*actor_requests).entry(request_id) {
Occupied(name) => { Occupied(name) => {
//TODO: Delete from map like Firefox does? //TODO: Delete from map like Firefox does?
name.into_mut().clone() name.into_mut().clone()
} },
Vacant(entry) => { Vacant(entry) => {
let actor_name = actors.new_name("netevent"); let actor_name = actors.new_name("netevent");
let actor = NetworkEventActor::new(actor_name.clone()); let actor = NetworkEventActor::new(actor_name.clone());
entry.insert(actor_name.clone()); entry.insert(actor_name.clone());
actors.register(Box::new(actor)); actors.register(Box::new(actor));
actor_name actor_name
} },
} }
} }
let sender_clone = sender.clone(); let sender_clone = sender.clone();
thread::Builder::new().name("DevtoolsClientAcceptor".to_owned()).spawn(move || { thread::Builder::new()
// accept connections and process them, spawning a new thread for each one .name("DevtoolsClientAcceptor".to_owned())
for stream in listener.incoming() { .spawn(move || {
// connection succeeded // accept connections and process them, spawning a new thread for each one
sender_clone.send(DevtoolsControlMsg::FromChrome( for stream in listener.incoming() {
ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()))).unwrap(); // connection succeeded
} sender_clone
}).expect("Thread spawning failed"); .send(DevtoolsControlMsg::FromChrome(
ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()),
)).unwrap();
}
}).expect("Thread spawning failed");
while let Ok(msg) = receiver.recv() { while let Ok(msg) = receiver.recv() {
match msg { match msg {
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => { DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => {
let actors = actors.clone(); let actors = actors.clone();
accepted_connections.push(stream.try_clone().unwrap()); accepted_connections.push(stream.try_clone().unwrap());
thread::Builder::new().name("DevtoolsClientHandler".to_owned()).spawn(move || { thread::Builder::new()
handle_client(actors, stream.try_clone().unwrap()) .name("DevtoolsClientHandler".to_owned())
}).expect("Thread spawning failed"); .spawn(move || handle_client(actors, stream.try_clone().unwrap()))
} .expect("Thread spawning failed");
},
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::FramerateTick( DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::FramerateTick(
actor_name, tick)) => actor_name,
handle_framerate_tick(actors.clone(), actor_name, tick), tick,
)) => handle_framerate_tick(actors.clone(), actor_name, tick),
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal( DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
ids, script_sender, pageinfo)) => ids,
handle_new_global(actors.clone(), ids, script_sender, &mut actor_pipelines, script_sender,
&mut actor_workers, pageinfo), pageinfo,
)) => handle_new_global(
actors.clone(),
ids,
script_sender,
&mut actor_pipelines,
&mut actor_workers,
pageinfo,
),
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI( DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI(
id, id,
console_message, console_message,
worker_id)) => worker_id,
handle_console_message(actors.clone(), id, worker_id, console_message, )) => handle_console_message(
&actor_pipelines, &actor_workers), actors.clone(),
id,
worker_id,
console_message,
&actor_pipelines,
&actor_workers,
),
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError( DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError(
id, id,
css_error)) => { css_error,
let console_message = ConsoleMessage { )) => {
let console_message = ConsoleMessage {
message: css_error.msg, message: css_error.msg,
logLevel: LogLevel::Warn, logLevel: LogLevel::Warn,
filename: css_error.filename, filename: css_error.filename,
lineNumber: css_error.line as usize, lineNumber: css_error.line as usize,
columnNumber: css_error.column as usize, columnNumber: css_error.column as usize,
}; };
handle_console_message(actors.clone(), id, None, console_message, handle_console_message(
&actor_pipelines, &actor_workers) actors.clone(),
id,
None,
console_message,
&actor_pipelines,
&actor_workers,
)
}, },
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent( DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent(
request_id, network_event)) => { request_id,
network_event,
)) => {
// copy the accepted_connections vector // copy the accepted_connections vector
let mut connections = Vec::<TcpStream>::new(); let mut connections = Vec::<TcpStream>::new();
for stream in &accepted_connections { for stream in &accepted_connections {
@ -523,10 +581,18 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
NetworkEvent::HttpResponse(ref response) => response.pipeline_id, NetworkEvent::HttpResponse(ref response) => response.pipeline_id,
NetworkEvent::HttpRequest(ref request) => request.pipeline_id, NetworkEvent::HttpRequest(ref request) => request.pipeline_id,
}; };
handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests, handle_network_event(
&actor_workers, pipeline_id, request_id, network_event); actors.clone(),
connections,
&actor_pipelines,
&mut actor_requests,
&actor_workers,
pipeline_id,
request_id,
network_event,
);
}, },
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg) => break DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg) => break,
} }
} }
for connection in &mut accepted_connections { for connection in &mut accepted_connections {

View file

@ -55,11 +55,11 @@ impl JsonPacketStream for TcpStream {
fn read_json_packet(&mut self) -> Result<Option<Value>, String> { fn read_json_packet(&mut self) -> Result<Option<Value>, String> {
// https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport // https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport
// In short, each JSON packet is [ascii length]:[JSON data of given length] // In short, each JSON packet is [ascii length]:[JSON data of given length]
let mut buffer = vec!(); let mut buffer = vec![];
loop { loop {
let mut buf = [0]; let mut buf = [0];
let byte = match self.read(&mut buf) { let byte = match self.read(&mut buf) {
Ok(0) => return Ok(None), // EOF Ok(0) => return Ok(None), // EOF
Ok(1) => buf[0], Ok(1) => buf[0],
Ok(_) => unreachable!(), Ok(_) => unreachable!(),
Err(e) => return Err(e.description().to_owned()), Err(e) => return Err(e.description().to_owned()),

View file

@ -8,7 +8,6 @@
#![crate_name = "devtools_traits"] #![crate_name = "devtools_traits"]
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
@ -17,9 +16,11 @@ extern crate bitflags;
extern crate hyper; extern crate hyper;
extern crate ipc_channel; extern crate ipc_channel;
extern crate malloc_size_of; extern crate malloc_size_of;
#[macro_use] extern crate malloc_size_of_derive; #[macro_use]
extern crate malloc_size_of_derive;
extern crate msg; extern crate msg;
#[macro_use] extern crate serde; #[macro_use]
extern crate serde;
extern crate servo_url; extern crate servo_url;
extern crate time; extern crate time;
@ -45,7 +46,7 @@ pub struct CSSError {
pub filename: String, pub filename: String,
pub line: u32, pub line: u32,
pub column: u32, pub column: u32,
pub msg: String pub msg: String,
} }
/// Messages to instruct the devtools server to update its known actors/state /// Messages to instruct the devtools server to update its known actors/state
@ -75,9 +76,11 @@ pub enum ChromeToDevtoolsControlMsg {
pub enum ScriptToDevtoolsControlMsg { pub enum ScriptToDevtoolsControlMsg {
/// A new global object was created, associated with a particular pipeline. /// A new global object was created, associated with a particular pipeline.
/// The means of communicating directly with it are provided. /// The means of communicating directly with it are provided.
NewGlobal((PipelineId, Option<WorkerId>), NewGlobal(
IpcSender<DevtoolScriptControlMsg>, (PipelineId, Option<WorkerId>),
DevtoolsPageInfo), IpcSender<DevtoolScriptControlMsg>,
DevtoolsPageInfo,
),
/// A particular page has invoked the console API. /// A particular page has invoked the console API.
ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>), ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>),
/// An animation frame with the given timestamp was processed in a script thread. /// An animation frame with the given timestamp was processed in a script thread.
@ -201,13 +204,21 @@ pub enum DevtoolScriptControlMsg {
/// Retrieve the computed layout properties of the given node in the given pipeline. /// Retrieve the computed layout properties of the given node in the given pipeline.
GetLayout(PipelineId, String, IpcSender<Option<ComputedNodeLayout>>), GetLayout(PipelineId, String, IpcSender<Option<ComputedNodeLayout>>),
/// Retrieve all stored console messages for the given pipeline. /// Retrieve all stored console messages for the given pipeline.
GetCachedMessages(PipelineId, CachedConsoleMessageTypes, IpcSender<Vec<CachedConsoleMessage>>), GetCachedMessages(
PipelineId,
CachedConsoleMessageTypes,
IpcSender<Vec<CachedConsoleMessage>>,
),
/// Update a given node's attributes with a list of modifications. /// Update a given node's attributes with a list of modifications.
ModifyAttribute(PipelineId, String, Vec<Modification>), ModifyAttribute(PipelineId, String, Vec<Modification>),
/// Request live console messages for a given pipeline (true if desired, false otherwise). /// Request live console messages for a given pipeline (true if desired, false otherwise).
WantsLiveNotifications(PipelineId, bool), WantsLiveNotifications(PipelineId, bool),
/// Request live notifications for a given set of timeline events for a given pipeline. /// Request live notifications for a given set of timeline events for a given pipeline.
SetTimelineMarkers(PipelineId, Vec<TimelineMarkerType>, IpcSender<Option<TimelineMarker>>), SetTimelineMarkers(
PipelineId,
Vec<TimelineMarkerType>,
IpcSender<Option<TimelineMarker>>,
),
/// Withdraw request for live timeline notifications for a given pipeline. /// Withdraw request for live timeline notifications for a given pipeline.
DropTimelineMarkers(PipelineId, Vec<TimelineMarkerType>), DropTimelineMarkers(PipelineId, Vec<TimelineMarkerType>),
/// Request a callback directed at the given actor name from the next animation frame /// Request a callback directed at the given actor name from the next animation frame