Add console message support to devtools. Does not actually cause logging to occur in the remote console.

This commit is contained in:
Sagar Muchhal 2015-02-05 19:52:35 +00:00 committed by Josh Matthews
parent 149053c2a7
commit 6699738cae
7 changed files with 112 additions and 16 deletions

View file

@ -15,3 +15,6 @@ path = "../msg"
[dependencies.util] [dependencies.util]
path = "../util" path = "../util"
[dependencies]
time = "*"

View file

@ -25,6 +25,7 @@ extern crate devtools_traits;
extern crate "serialize" as rustc_serialize; extern crate "serialize" as rustc_serialize;
extern crate serialize; extern crate serialize;
extern crate "msg" as servo_msg; extern crate "msg" as servo_msg;
extern crate time;
extern crate util; extern crate util;
use actor::{Actor, ActorRegistry}; use actor::{Actor, ActorRegistry};
@ -34,7 +35,8 @@ use actors::root::RootActor;
use actors::tab::TabActor; use actors::tab::TabActor;
use protocol::JsonPacketStream; use protocol::JsonPacketStream;
use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg, DevtoolsPageInfo}; use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg};
use devtools_traits::{DevtoolsPageInfo, SendConsoleMessage, ConsoleMessage};
use servo_msg::constellation_msg::PipelineId; use servo_msg::constellation_msg::PipelineId;
use util::task::spawn_named; use util::task::spawn_named;
@ -46,6 +48,7 @@ use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream}; use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut}; use std::io::{Acceptor, Listener, TimedOut};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use time::precise_time_ns;
mod actor; mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/ /// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
@ -57,6 +60,20 @@ mod actors {
} }
mod protocol; mod protocol;
#[derive(RustcEncodable)]
struct ConsoleAPICall {
from: String,
__type__: String,
message: ConsoleMsg,
}
#[derive(RustcEncodable)]
struct ConsoleMsg {
logLevel: u32,
timestamp: u64,
message: String,
}
/// Spin up a devtools server that listens for connections on the specified port. /// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> { pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
let (sender, receiver) = channel(); let (sender, receiver) = channel();
@ -169,6 +186,41 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
actors.register(box inspector); actors.register(box inspector);
} }
fn handle_console_message(actors: Arc<Mutex<ActorRegistry>>,
id: PipelineId,
console_message: ConsoleMessage,
actor_pipelines: &HashMap<PipelineId, String>) {
let console_actor_name = find_console_actor(actors.clone(), id, actor_pipelines);
let actors = actors.lock().unwrap();
let console_actor = actors.find::<ConsoleActor>(console_actor_name.as_slice());
match console_message {
ConsoleMessage::LogMessage(message) => {
let msg = ConsoleAPICall {
from: console_actor.name.clone(),
__type__: "consoleAPICall".to_string(),
message: ConsoleMsg {
logLevel: 0,
timestamp: precise_time_ns(),
message: message,
},
};
for stream in console_actor.streams.borrow_mut().iter_mut() {
stream.write_json_packet(&msg);
}
}
}
}
fn find_console_actor(actors: Arc<Mutex<ActorRegistry>>,
id: PipelineId,
actor_pipelines: &HashMap<PipelineId, String>) -> String {
let actors = actors.lock().unwrap();
let ref tab_actor_name = (*actor_pipelines)[id];
let tab_actor = actors.find::<TabActor>(tab_actor_name.as_slice());
let console_actor_name = tab_actor.console.clone();
return console_actor_name;
}
//TODO: figure out some system that allows us to watch for new connections, //TODO: figure out some system that allows us to watch for new connections,
// shut down existing ones at arbitrary times, and also watch for messages // shut down existing ones at arbitrary times, and also watch for messages
// from multiple script tasks simultaneously. Polling for new connections // from multiple script tasks simultaneously. Polling for new connections
@ -180,7 +232,12 @@ fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
Err(ref e) if e.kind == TimedOut => { Err(ref e) if e.kind == TimedOut => {
match receiver.try_recv() { match receiver.try_recv() {
Ok(ServerExitMsg) | Err(Disconnected) => break, Ok(ServerExitMsg) | Err(Disconnected) => break,
Ok(NewGlobal(id, sender, pageinfo)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines, pageinfo), Ok(NewGlobal(id, sender, pageinfo)) =>
handle_new_global(actors.clone(), id,sender, &mut actor_pipelines,
pageinfo),
Ok(SendConsoleMessage(id, console_message)) =>
handle_console_message(actors.clone(), id, console_message,
&actor_pipelines),
Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)), Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
} }
} }

View file

@ -45,6 +45,7 @@ pub struct DevtoolsPageInfo {
/// according to changes in the browser. /// according to changes in the browser.
pub enum DevtoolsControlMsg { pub enum DevtoolsControlMsg {
NewGlobal(PipelineId, Sender<DevtoolScriptControlMsg>, DevtoolsPageInfo), NewGlobal(PipelineId, Sender<DevtoolScriptControlMsg>, DevtoolsPageInfo),
SendConsoleMessage(PipelineId, ConsoleMessage),
ServerExitMsg ServerExitMsg
} }
@ -123,3 +124,10 @@ impl Decodable for Modification {
) )
} }
} }
//TODO: Include options for Warn, Debug, Info, Error messages from Console
#[derive(Clone)]
pub enum ConsoleMessage {
LogMessage(String),
//WarnMessage(String),
}

View file

@ -4,31 +4,35 @@
use dom::bindings::codegen::Bindings::ConsoleBinding; use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods; use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use devtools_traits::{SendConsoleMessage, ConsoleMessage};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
pub struct Console { pub struct Console {
reflector_: Reflector reflector_: Reflector,
global: GlobalField,
} }
impl Console { impl Console {
fn new_inherited() -> Console { fn new_inherited(global: GlobalRef) -> Console {
Console { Console {
reflector_: Reflector::new() reflector_: Reflector::new(),
global: GlobalField::from_rooted(&global),
} }
} }
pub fn new(global: GlobalRef) -> Temporary<Console> { pub fn new(global: GlobalRef) -> Temporary<Console> {
reflect_dom_object(box Console::new_inherited(), global, ConsoleBinding::Wrap) reflect_dom_object(box Console::new_inherited(global), global, ConsoleBinding::Wrap)
} }
} }
impl<'a> ConsoleMethods for JSRef<'a, Console> { impl<'a> ConsoleMethods for JSRef<'a, Console> {
fn Log(self, message: DOMString) { fn Log(self, message: DOMString) {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, ConsoleMessage::LogMessage(message));
} }
fn Debug(self, message: DOMString) { fn Debug(self, message: DOMString) {
@ -58,3 +62,18 @@ impl<'a> ConsoleMethods for JSRef<'a, Console> {
} }
} }
fn propagate_console_msg(console: &JSRef<Console>, console_message: ConsoleMessage) {
let global = console.global.root();
match global.r() {
GlobalRef::Window(window_ref) => {
let pipelineId = window_ref.page().id;
console.global.root().r().as_window().page().devtools_chan.as_ref().map(|chan| {
chan.send(SendConsoleMessage(pipelineId, console_message.clone())).unwrap();
});
},
GlobalRef::Worker(_) => {
// TODO: support worker console logs
}
}
}

View file

@ -11,6 +11,7 @@ use dom::document::{Document, DocumentHelpers};
use dom::element::Element; use dom::element::Element;
use dom::node::{Node, NodeHelpers}; use dom::node::{Node, NodeHelpers};
use dom::window::Window; use dom::window::Window;
use devtools_traits::DevtoolsControlChan;
use layout_interface::{ use layout_interface::{
ContentBoxResponse, ContentBoxesResponse, ContentBoxResponse, ContentBoxesResponse,
HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse, Msg, Reflow, HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse, Msg, Reflow,
@ -100,6 +101,9 @@ pub struct Page {
/// A flag to indicate whether the developer tools have requested live updates of /// A flag to indicate whether the developer tools have requested live updates of
/// page changes. /// page changes.
pub devtools_wants_updates: Cell<bool>, pub devtools_wants_updates: Cell<bool>,
/// For providing instructions to an optional devtools server.
pub devtools_chan: Option<DevtoolsControlChan>,
} }
pub struct PageIterator { pub struct PageIterator {
@ -135,7 +139,8 @@ impl Page {
resource_task: ResourceTask, resource_task: ResourceTask,
storage_task: StorageTask, storage_task: StorageTask,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
js_context: Rc<Cx>) -> Page { js_context: Rc<Cx>,
devtools_chan: Option<DevtoolsControlChan>) -> Page {
let js_info = JSPageInfo { let js_info = JSPageInfo {
dom_static: GlobalStaticData::new(), dom_static: GlobalStaticData::new(),
js_context: js_context, js_context: js_context,
@ -166,6 +171,7 @@ impl Page {
children: DOMRefCell::new(vec!()), children: DOMRefCell::new(vec!()),
page_clip_rect: Cell::new(MAX_RECT), page_clip_rect: Cell::new(MAX_RECT),
devtools_wants_updates: Cell::new(false), devtools_wants_updates: Cell::new(false),
devtools_chan: devtools_chan,
} }
} }

View file

@ -379,7 +379,8 @@ impl ScriptTask {
resource_task.clone(), resource_task.clone(),
storage_task, storage_task,
constellation_chan.clone(), constellation_chan.clone(),
js_context.clone()); js_context.clone(),
devtools_chan.clone());
let (devtools_sender, devtools_receiver) = channel(); let (devtools_sender, devtools_receiver) = channel();
ScriptTask { ScriptTask {
@ -662,7 +663,8 @@ impl ScriptTask {
parent_page.resource_task.clone(), parent_page.resource_task.clone(),
parent_page.storage_task.clone(), parent_page.storage_task.clone(),
self.constellation_chan.clone(), self.constellation_chan.clone(),
self.js_context.borrow().as_ref().unwrap().clone()) self.js_context.borrow().as_ref().unwrap().clone(),
self.devtools_chan.clone())
}; };
parent_page.children.borrow_mut().push(Rc::new(new_page)); parent_page.children.borrow_mut().push(Rc::new(new_page));
} }

View file

@ -145,6 +145,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"msg 0.0.1", "msg 0.0.1",
"time 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1", "util 0.0.1",
] ]