From 6e91ebb1fe2932655c191a26a4ca4770231e69f3 Mon Sep 17 00:00:00 2001 From: Himaja Date: Sun, 26 Apr 2015 20:51:46 -0400 Subject: [PATCH] 1. Add an enum type NetworkEventMessage for handling both HttpRequest and HttpResponse messages 2. Change run_server to handle network events 3. Add a unique id to track request-actor associations 4. Update the network event actor --- components/devtools/actors/network_event.rs | 139 ++++++++++++++++++-- components/devtools/lib.rs | 128 +++++++++++------- components/devtools_traits/lib.rs | 9 +- components/net/http_loader.rs | 25 ++-- components/net/lib.rs | 1 + 5 files changed, 230 insertions(+), 72 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; -#[derive(RustcEncodable)] -pub struct HttpRequest { - pub url: Url, - //method: Method, - //headers: Headers, - pub body: Option>, +struct HttpRequest { + url: String, + method: Method, + headers: Headers, + body: Option>, +} + +struct HttpResponse { + headers: Option, + status: Option, + body: Option> } #[derive(RustcEncodable)] +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, let mut accepted_connections: Vec = Vec::new(); let mut actor_pipelines: HashMap = HashMap::new(); + let mut actor_requests: HashMap = HashMap::new(); let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); @@ -279,46 +279,72 @@ fn run_server(sender: Sender, return console_actor_name; } - fn handle_network_event(actors: Arc>, - connections: RefCell>, - url: Url, - method: Method, - headers: Headers, - body: Option>) { - - //println!("handle_network_event"); + fn find_first_console_actor(actors: Arc>) -> String { + let actors = actors.lock().unwrap(); + let root = actors.find::("root"); + let ref tab_actor_name = root.tabs[0]; + let tab_actor = actors.find::(tab_actor_name); + let console_actor_name = tab_actor.console.clone(); + return console_actor_name; + } + + fn find_network_event_actor(actors: Arc>, + actor_requests: &mut HashMap, + 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 + } + } + } - /* 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. - */ + fn handle_network_event(actors: Arc>, + mut accepted_connections: Vec, + actor_requests: &mut HashMap, + request_id: String, + network_event: NetworkEvent) { - let actor = NetworkEventActor { - name: actors.new_name("network_event"), - request: HttpRequest { - url: url.clone(), - //method: method.clone(), - //headers: headers.clone(), - body: body.clone() - }, - }; + 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::(&netevent_actor_name); - 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(), - }, - }; + 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); + } + } - for stream in connections.borrow_mut().iter_mut() { - stream.write_json_packet(&msg); + 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 accepted_connections.iter_mut() { + stream.write_json_packet(&msg); + } + } } } @@ -347,14 +373,14 @@ fn run_server(sender: Sender, 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::::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::::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), Sender, DevtoolsPageInfo), SendConsoleMessage(PipelineId, ConsoleMessage), ServerExitMsg, - HttpRequest(Url, Method, Headers, Option>), - HttpResponse(Option, RawStatus, Vec) + 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>), + HttpResponse(Option, Option, Option>) +} + 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;