diff options
-rw-r--r-- | components/devtools/actors/network_event.rs | 137 | ||||
-rw-r--r-- | components/devtools/lib.rs | 128 | ||||
-rw-r--r-- | components/devtools_traits/lib.rs | 9 | ||||
-rw-r--r-- | components/net/http_loader.rs | 25 | ||||
-rw-r--r-- | components/net/lib.rs | 1 |
5 files changed, 229 insertions, 71 deletions
diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs index 24e63f6a5b4..a608234ad96 100644 --- a/components/devtools/actors/network_event.rs +++ b/components/devtools/actors/network_event.rs @@ -14,31 +14,68 @@ use protocol::JsonPacketStream; use devtools_traits::DevtoolScriptControlMsg; use msg::constellation_msg::PipelineId; +use devtools_traits::{DevtoolsControlMsg, NetworkEvent}; use collections::BTreeMap; use core::cell::RefCell; +use std::fmt; use rustc_serialize::json::{self, Json, ToJson}; use std::net::TcpStream; use std::num::Float; use std::sync::mpsc::{channel, Sender}; +use std::borrow::IntoCow; use url::Url; use hyper::header::Headers; use hyper::http::RawStatus; use hyper::method::Method; +struct HttpRequest { + url: String, + method: Method, + headers: Headers, + body: Option<Vec<u8>>, +} + +struct HttpResponse { + headers: Option<Headers>, + status: Option<RawStatus>, + body: Option<Vec<u8>> +} + #[derive(RustcEncodable)] -pub struct HttpRequest { - pub url: Url, - //method: Method, - //headers: Headers, - pub body: Option<Vec<u8>>, +struct GetRequestHeadersReply { + from: String, + headers: String, + headerSize: u8, + rawHeaders: String } #[derive(RustcEncodable)] +pub struct EventActor { + pub actor: String, + pub url: String, + pub method: String, + pub startedDateTime: String, + pub isXHR: String, + pub private: String +} + +#[derive(RustcEncodable)] +pub struct ResponseStartMsg { + pub httpVersion: String, + pub remoteAddress: String, + pub remotePort: u8, + pub status: String, + pub statusText: String, + pub headersSize: u8, + pub discardResponseBody: bool, +} + pub struct NetworkEventActor { pub name: String, - pub request: HttpRequest, + request: HttpRequest, + response: HttpResponse, } impl Actor for NetworkEventActor { @@ -54,11 +91,39 @@ impl Actor for NetworkEventActor { Ok(match msg_type { "getRequestHeaders" => { - //stream.write_json_packet(&msg); + println!("getRequestHeaders"); + let msg = GetRequestHeadersReply { + from: self.name(), + headers: "headers".to_string(), + headerSize: 10, + rawHeaders: "Raw headers".to_string(), + }; + stream.write_json_packet(&msg); true } "getRequestCookies" => { + println!("getRequestCookies"); + true + } + + "getRequestPostData" => { + println!("getRequestPostData"); + true + } + + "getResponseHeaders" => { + println!("getResponseHeaders"); + true + } + + "getResponseCookies" => { + println!("getResponseCookies"); + true + } + + "getResponseContent" => { + println!("getResponseContent"); true } @@ -66,3 +131,61 @@ impl Actor for NetworkEventActor { }) } } + +impl NetworkEventActor { + pub fn new(name: String) -> NetworkEventActor { + NetworkEventActor { + name: name, + request: HttpRequest { + url: String::new(), + method: Method::Get, + headers: Headers::new(), + body: None + }, + response: HttpResponse { + headers: None, + status: None, + body: None, + } + } + } + + pub fn addEvent(&mut self, network_event: NetworkEvent) { + match network_event { + NetworkEvent::HttpRequest(url, method, headers, body) => { + self.request.url = url.serialize(); + self.request.method = method.clone(); + self.request.headers = headers.clone(); + self.request.body = body; + } + NetworkEvent::HttpResponse(headers, status, body) => { + self.response.headers = headers.clone(); + self.response.status = status.clone(); + self.response.body = body.clone(); + } + } + } + + pub fn get_event_actor(&self) -> EventActor { + EventActor { + actor: self.name(), + url: self.request.url.clone(), + method: format!("{}", self.request.method), + startedDateTime: "2015-04-22T20:47:08.545Z".to_string(), + isXHR: "false".to_string(), + private: "false".to_string(), + } + } + + pub fn get_response_start(&self) -> ResponseStartMsg { + ResponseStartMsg { + httpVersion: "HTTP/1.1".to_string(), + remoteAddress: "63.245.217.43".to_string(), + remotePort: 443, + status: "200".to_string(), + statusText: "OK".to_string(), + headersSize: 337, + discardResponseBody: true + } + } +} diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index 220c10b63b9..604c14b3ba6 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -30,8 +30,7 @@ extern crate hyper; use actor::{Actor, ActorRegistry}; use actors::console::ConsoleActor; -use actors::network_event::NetworkEventActor; -use actors::network_event::{HttpRequest}; +use actors::network_event::{NetworkEventActor, EventActor, ResponseStartMsg}; use actors::worker::WorkerActor; use actors::inspector::InspectorActor; use actors::root::RootActor; @@ -39,7 +38,7 @@ use actors::tab::TabActor; use actors::timeline::TimelineActor; use protocol::JsonPacketStream; -use devtools_traits::{ConsoleMessage, DevtoolsControlMsg}; +use devtools_traits::{ConsoleMessage, DevtoolsControlMsg, NetworkEvent}; use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg}; use msg::constellation_msg::{PipelineId, WorkerId}; use util::task::spawn_named; @@ -47,6 +46,7 @@ use util::task::spawn_named; use std::borrow::ToOwned; use std::cell::RefCell; use std::collections::HashMap; +use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::error::Error; use std::sync::mpsc::{channel, Receiver, Sender, RecvError}; use std::net::{TcpListener, TcpStream, Shutdown}; @@ -99,12 +99,11 @@ struct NetworkEventMsg { } #[derive(RustcEncodable)] -struct EventActor { - actor: NetworkEventActor, - url: String, - method: String, - startedDateTime: String, - isXHR: String, +struct NetworkEventUpdateMsg { + from: String, + __type__: String, + updateType: String, + response: ResponseStartMsg, } /// Spin up a devtools server that listens for connections on the specified port. @@ -138,6 +137,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, let mut accepted_connections: Vec<TcpStream> = Vec::new(); let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new(); + let mut actor_requests: HashMap<String, String> = HashMap::new(); let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); @@ -279,46 +279,72 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, return console_actor_name; } + fn find_first_console_actor(actors: Arc<Mutex<ActorRegistry>>) -> String { + let actors = actors.lock().unwrap(); + let root = actors.find::<RootActor>("root"); + let ref tab_actor_name = root.tabs[0]; + let tab_actor = actors.find::<TabActor>(tab_actor_name); + let console_actor_name = tab_actor.console.clone(); + return console_actor_name; + } + + fn find_network_event_actor(actors: Arc<Mutex<ActorRegistry>>, + actor_requests: &mut HashMap<String, String>, + request_id: String) -> String { + let mut actors = actors.lock().unwrap(); + match (*actor_requests).entry(request_id) { + Occupied(name) => { + name.into_mut().clone() + } + Vacant(entry) => { + println!("not found"); + let actor_name = actors.new_name("netevent"); + let actor = NetworkEventActor::new(actor_name.clone()); + entry.insert(actor_name.clone()); + actors.register(box actor); + actor_name + } + } + } + fn handle_network_event(actors: Arc<Mutex<ActorRegistry>>, - connections: RefCell<Vec<TcpStream>>, - url: Url, - method: Method, - headers: Headers, - body: Option<Vec<u8>>) { + mut accepted_connections: Vec<TcpStream>, + actor_requests: &mut HashMap<String, String>, + request_id: String, + network_event: NetworkEvent) { - //println!("handle_network_event"); + let console_actor_name = find_first_console_actor(actors.clone()); + let netevent_actor_name = find_network_event_actor(actors.clone(), actor_requests, request_id.clone()); let mut actors = actors.lock().unwrap(); + let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name); + + match network_event { + NetworkEvent::HttpRequest(..) => { + actor.addEvent(network_event); + let msg = NetworkEventMsg { + from: console_actor_name, + __type__: "networkEvent".to_string(), + eventActor: actor.get_event_actor(), + }; + for stream in accepted_connections.iter_mut() { + stream.write_json_packet(&msg); + } + } - /* TODO: Maintain a HashMap that maps request/response ID to actor name. - * Check if the map contains the ID of the request/response message. - * If no actor exists, create a new one. - * Store to stream(s) to the actor and retrieve them. - */ - - let actor = NetworkEventActor { - name: actors.new_name("network_event"), - request: HttpRequest { - url: url.clone(), - //method: method.clone(), - //headers: headers.clone(), - body: body.clone() - }, - }; - - let msg = NetworkEventMsg { - from: actor.name.clone(), - __type__: "networkEvent".to_string(), - eventActor: EventActor { - actor: actor, - url: url.serialize(), - method: "".to_string(), - startedDateTime: "".to_string(), - isXHR: "false".to_string(), - }, - }; + NetworkEvent::HttpResponse(..) => { + println!("Network event response"); + actor.addEvent(network_event); + let msg = NetworkEventUpdateMsg { + from: netevent_actor_name, + __type__: "networkEventUpdate".to_string(), + updateType: "responseStart".to_string(), + response: actor.get_response_start() + }; - for stream in connections.borrow_mut().iter_mut() { - stream.write_json_packet(&msg); + for stream in accepted_connections.iter_mut() { + stream.write_json_packet(&msg); + } + } } } @@ -347,14 +373,14 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, handle_console_message(actors.clone(), id, console_message, &actor_pipelines), - Ok(DevtoolsControlMsg::HttpRequest(url, method, headers, body)) => { - //println!("run_server: HttpRequest"); - let connections = RefCell::new(Vec::<TcpStream>::new()); - let mut stream = accepted_connections.get_mut(0).unwrap(); - connections.borrow_mut().push(stream.try_clone().unwrap()); - handle_network_event(actors.clone(), connections, url, method, headers, body); + Ok(DevtoolsControlMsg::NetworkEventMessage(request_id, network_event)) => { + // copy the accepted_connections vector + let mut connections = Vec::<TcpStream>::new(); + for stream in accepted_connections.iter() { + connections.push(stream.try_clone().unwrap()); + } + handle_network_event(actors.clone(), connections, &mut actor_requests, request_id, network_event); } - _ => break, } } diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index df7eb0ac632..4ab74a9e1de 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -47,8 +47,7 @@ pub enum DevtoolsControlMsg { NewGlobal((PipelineId, Option<WorkerId>), Sender<DevtoolScriptControlMsg>, DevtoolsPageInfo), SendConsoleMessage(PipelineId, ConsoleMessage), ServerExitMsg, - HttpRequest(Url, Method, Headers, Option<Vec<u8>>), - HttpResponse(Option<Headers>, RawStatus, Vec<u8>) + NetworkEventMessage(String, NetworkEvent), } /// Serialized JS return values @@ -152,6 +151,12 @@ pub enum ConsoleMessage { //WarnMessage(String), } +#[derive(Clone)] +pub enum NetworkEvent { + HttpRequest(Url, Method, Headers, Option<Vec<u8>>), + HttpResponse(Option<Headers>, Option<RawStatus>, Option<Vec<u8>>) +} + impl TimelineMarker { pub fn new(name: String, metadata: TracingMetadata) -> TimelineMarker { TimelineMarker { diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 9d36e9f247d..1f3e45d387f 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -4,7 +4,7 @@ use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; -use devtools_traits::{DevtoolsControlMsg}; +use devtools_traits::{DevtoolsControlMsg, NetworkEvent}; use mime_classifier::MIMEClassifier; use resource_task::{start_sending_opt, start_sending_sniffed_opt}; @@ -29,6 +29,7 @@ use util::resource_files::resources_dir_path; use util::opts; use url::{Url, UrlParser}; +use uuid; use std::borrow::ToOwned; use std::boxed::FnBox; @@ -199,16 +200,14 @@ reason: \"certificate verify failed\" }]))"; info!("{:?}", load_data.data); } -/* - match devtools_chan { - Some(chan) => chan.send(DevtoolsControlMsg::HttpRequest(load_data.url.clone(), load_data.method.clone(), load_data.headers.clone(), load_data.data.clone())).unwrap(), - None => {} - } -*/ - - println!("load"); - devtools_chan.as_ref().map(|chan| chan.send(DevtoolsControlMsg::HttpRequest(load_data.url.clone(), load_data.method.clone(), load_data.headers.clone(), load_data.data.clone())).unwrap()); - + let request_id = uuid::Uuid::new_v4().to_simple_string(); + let net_event = NetworkEvent::HttpRequest( + load_data.url.clone(), + load_data.method.clone(), + load_data.headers.clone(), + load_data.data.clone() + ); + devtools_chan.as_ref().map(|chan| chan.send(DevtoolsControlMsg::NetworkEventMessage(request_id.clone(), net_event))); // Avoid automatically sending request body if a redirect has occurred. let writer = match load_data.data { @@ -342,6 +341,10 @@ reason: \"certificate verify failed\" }]))"; } } + println!("Http loader Response"); + let net_event_response = NetworkEvent::HttpResponse(metadata.headers.clone(), metadata.status.clone(), None); + devtools_chan.as_ref().map(|chan| chan.send(DevtoolsControlMsg::NetworkEventMessage(request_id, net_event_response))); + match encoding_str { Some(encoding) => { if encoding == "gzip" { diff --git a/components/net/lib.rs b/components/net/lib.rs index b64c38b0f49..8379211b36f 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -29,6 +29,7 @@ extern crate rustc_serialize; extern crate util; extern crate time; extern crate url; +extern crate uuid; extern crate regex; |