Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M1453: Review for GetCachedMessages #4175

Closed
wants to merge 9 commits into from
@@ -9,11 +9,12 @@
use actor::{Actor, ActorRegistry};
use protocol::JsonPacketSender;

use devtools_traits::{EvaluateJS, NullValue, VoidValue, NumberValue, StringValue, BooleanValue};
use devtools_traits::{ActorValue, DevtoolScriptControlMsg};
use devtools_traits::{EvaluateJS, NullValue, VoidValue, NumberValue, StringValue, BooleanValue, GetCachedMessages};
use devtools_traits::{ActorValue, DevtoolScriptControlMsg, CachedMessageType};
use servo_msg::constellation_msg::PipelineId;

use collections::TreeMap;
use core::cell::RefCell;
use serialize::json;
use serialize::json::ToJson;
use std::io::TcpStream;
@@ -70,7 +71,7 @@ enum ConsoleMessageType {
#[deriving(Encodable)]
struct GetCachedMessagesReply {
from: String,
messages: Vec<json::JsonObject>,
messages: Vec<CachedMessageType>,
}

#[deriving(Encodable)]
@@ -97,10 +98,16 @@ struct EvaluateJSReply {
helperResult: json::Json,
}

#[deriving(Encodable)]
struct CachedMessage {
pub messageType: String,
}

pub struct ConsoleActor {
pub name: String,
pub pipeline: PipelineId,
pub script_chan: Sender<DevtoolScriptControlMsg>,
pub streams: RefCell<Vec<TcpStream>>,
}

impl Actor for ConsoleActor {
@@ -116,7 +123,14 @@ impl Actor for ConsoleActor {
match msg_type.as_slice() {
"getCachedMessages" => {
let types = msg.find(&"messageTypes".to_string()).unwrap().as_list().unwrap();
let /*mut*/ messages = vec!();
let (chan, port) = channel();
let mut cachedmsg: Vec<String> = Vec::new();
for json_mod in types.iter() {
let message: String = json::decode(json_mod.to_string().as_slice()).unwrap();
cachedmsg.push(message);
}
self.script_chan.send(GetCachedMessages(cachedmsg , chan));
let cachedReply = port.recv();
for msg_type in types.iter() {
let msg_type = msg_type.as_string().unwrap();
match msg_type.as_slice() {
@@ -162,7 +176,7 @@ impl Actor for ConsoleActor {

let msg = GetCachedMessagesReply {
from: self.name(),
messages: messages,
messages: cachedReply,
};
stream.write_json_packet(&msg);
true
@@ -5,7 +5,7 @@
/// Liberally derived from the [Firefox JS implementation](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js).

use devtools_traits::{GetRootNode, GetDocumentElement, GetChildren, DevtoolScriptControlMsg};
use devtools_traits::{GetLayout, NodeInfo};
use devtools_traits::{GetLayout, NodeInfo, ModifyAttribute};

use actor::{Actor, ActorRegistry};
use protocol::JsonPacketSender;
@@ -41,6 +41,12 @@ struct HighlighterActor {
name: String,
}

pub struct NodeActor {
pub name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}

#[deriving(Encodable)]
struct ShowBoxModelReply {
from: String,
@@ -52,7 +58,7 @@ struct HideBoxModelReply {
}

impl Actor for HighlighterActor {
fn name(&self) -> String {
fn name(&self) -> String {
self.name.clone()
}

@@ -83,6 +89,44 @@ impl Actor for HighlighterActor {
}
}

#[deriving(Encodable)]
struct ModifyAttributeReply{
from: String,
}

impl Actor for NodeActor {
fn name(&self) -> String {
self.name.clone()
}

fn handle_message(&self,
registry: &ActorRegistry,
msg_type: &String,
msg: &json::JsonObject,
stream: &mut TcpStream) -> bool {
match msg_type.as_slice() {
"modifyAttributes" => {
let target = msg.find(&"to".to_string()).unwrap().as_string().unwrap();
let mods = msg.find(&"modifications".to_string()).unwrap().as_list().unwrap();
let modifications = mods.iter().map(|json_mod| {
json::decode(json_mod.to_string().as_slice()).unwrap()
}).collect();

self.script_chan.send(ModifyAttribute(self.pipeline,
registry.actor_to_script(target.to_string()),
modifications));
let reply = ModifyAttributeReply{
from: self.name(),
};
stream.write_json_packet(&reply);
true
}

_ => false,
}
}
}

#[deriving(Encodable)]
struct GetWalkerReply {
from: String,
@@ -131,14 +175,28 @@ struct NodeActorMsg {
}

trait NodeInfoToProtocol {
fn encode(self, actors: &ActorRegistry, display: bool) -> NodeActorMsg;
fn encode(self,
actors: &ActorRegistry,
display: bool,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId) -> NodeActorMsg;
}

impl NodeInfoToProtocol for NodeInfo {
fn encode(self, actors: &ActorRegistry, display: bool) -> NodeActorMsg {
fn encode(self,
actors: &ActorRegistry,
display: bool,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId) -> NodeActorMsg {
let actor_name = if !actors.script_actor_registered(self.uniqueId.clone()) {
let name = actors.new_name("node");
let node_actor = NodeActor {
name: name.clone(),
script_chan: script_chan,
pipeline: pipeline.clone(),
};
actors.register_script_actor(self.uniqueId, name.clone());
actors.register_later(box node_actor);
name
} else {
actors.script_to_actor(self.uniqueId)
@@ -232,8 +290,7 @@ impl Actor for WalkerActor {
let (tx, rx) = channel();
self.script_chan.send(GetDocumentElement(self.pipeline, tx));
let doc_elem_info = rx.recv();

let node = doc_elem_info.encode(registry, true);
let node = doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline);

let msg = DocumentElementReply {
from: self.name(),
@@ -263,7 +320,7 @@ impl Actor for WalkerActor {
hasFirst: true,
hasLast: true,
nodes: children.into_iter().map(|child| {
child.encode(registry, true)
child.encode(registry, true, self.script_chan.clone(), self.pipeline)
}).collect(),
from: self.name(),
};
@@ -452,7 +509,7 @@ impl Actor for InspectorActor {
self.script_chan.send(GetRootNode(self.pipeline, tx));
let root_info = rx.recv();

let node = root_info.encode(registry, false);
let node = root_info.encode(registry, false, self.script_chan.clone(), self.pipeline);

let msg = GetWalkerReply {
from: self.name(),
@@ -7,6 +7,7 @@
/// Supports dynamic attaching and detaching which control notifications of navigation, etc.

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use protocol::JsonPacketSender;

use serialize::json;
@@ -74,7 +75,7 @@ impl Actor for TabActor {
}

fn handle_message(&self,
_registry: &ActorRegistry,
registry: &ActorRegistry,
msg_type: &String,
_msg: &json::JsonObject,
stream: &mut TcpStream) -> bool {
@@ -95,15 +96,21 @@ impl Actor for TabActor {
javascriptEnabled: true,
traits: TabTraits,
};
let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
console_actor.streams.borrow_mut().push(stream.clone());
stream.write_json_packet(&msg);
true
}

//FIXME: The current implementation won't work for multiple connections. Need to ensure
// that the correct stream is removed.
"detach" => {
let msg = TabDetachedReply {
from: self.name(),
__type__: "detached".to_string(),
};
let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
console_actor.streams.borrow_mut().pop();
stream.write_json_packet(&msg);
true
}
@@ -41,6 +41,7 @@ use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;

use std::cell::RefCell;
use std::collections::HashMap;
use std::comm;
use std::comm::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
@@ -90,6 +91,8 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {

let mut accepted_connections: Vec<TcpStream> = Vec::new();

let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();

/// Process the input from a single devtools client until EOF.
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
println!("connection established to {:?}", stream.peer_name().unwrap());
@@ -138,15 +141,16 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
// TODO: move this into the root or tab modules?
fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
pipeline: PipelineId,
sender: Sender<DevtoolScriptControlMsg>) {
sender: Sender<DevtoolScriptControlMsg>,
actor_pipelines: &mut HashMap<PipelineId, String>) {
let mut actors = actors.lock();

//TODO: move all this actor creation into a constructor method on TabActor
let (tab, console, inspector) = {
let console = ConsoleActor {
name: actors.new_name("console"),
script_chan: sender.clone(),
pipeline: pipeline,
streams: RefCell::new(Vec::new()),
};
let inspector = InspectorActor {
name: actors.new_name("inspector"),
@@ -170,6 +174,7 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
(tab, console, inspector)
};

actor_pipelines.insert(pipeline, tab.name.clone());
actors.register(box tab);
actors.register(box console);
actors.register(box inspector);
@@ -186,7 +191,7 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
Err(ref e) if e.kind == TimedOut => {
match receiver.try_recv() {
Ok(ServerExitMsg) | Err(Disconnected) => break,
Ok(NewGlobal(id, sender)) => handle_new_global(actors.clone(), id, sender),
Ok(NewGlobal(id, sender)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines),
Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
}
}
@@ -11,11 +11,12 @@
#![allow(non_snake_case)]

extern crate "msg" as servo_msg;

extern crate serialize;
/// This module contains shared types and messages for use by devtools/script.
/// The traits are here instead of in script so that the devtools crate can be
/// modified independently of the rest of Servo.

use serialize::{Decodable, Decoder};
use servo_msg::constellation_msg::PipelineId;

pub type DevtoolsControlChan = Sender<DevtoolsControlMsg>;
@@ -73,6 +74,8 @@ pub enum DevtoolScriptControlMsg {
GetDocumentElement(PipelineId, Sender<NodeInfo>),
GetChildren(PipelineId, String, Sender<Vec<NodeInfo>>),
GetLayout(PipelineId, String, Sender<(f32, f32)>),
ModifyAttribute(PipelineId, String, Vec<Modification>),
GetCachedMessages(Vec<String>, Sender<Vec<CachedMessageType>>)
}

/// Messages to instruct devtools server to update its state relating to a particular
@@ -81,3 +84,45 @@ pub enum ScriptDevtoolControlMsg {
/// Report a new JS error message
ReportConsoleMsg(String),
}

#[deriving(Encodable)]
pub struct Modification{
pub attributeName: String,
pub newValue: Option<String>,
}

impl<D:Decoder<E>, E> Decodable<D, E> for Modification {
fn decode(d: &mut D) -> Result<Modification, E> {
d.read_struct("Modification", 2u, |d|
Ok(Modification {
attributeName: try!(d.read_struct_field("attributeName", 0u, |d| Decodable::decode(d))),
newValue: match d.read_struct_field("newValue", 1u, |d| Decodable::decode(d)) {
Ok(opt) => opt,
Err(_) => None
}
})
)
}
}

#[deriving(Encodable)]
pub struct ConsoleAPIMessage {
_type: String,
}

#[deriving(Encodable)]
pub struct PageErrorMessage {
_type: String,
}

#[deriving(Encodable)]
pub struct LogMessage {
_type: String,
}

#[deriving(Encodable)]
pub enum CachedMessageType {
ConsoleAPIType(ConsoleAPIMessage),
PageErrorType(PageErrorMessage),
LogMessageType(LogMessage),
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.