diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs index a6282b71918..38f7d5767df 100644 --- a/components/devtools/actors/network_event.rs +++ b/components/devtools/actors/network_event.rs @@ -27,7 +27,10 @@ struct HttpRequest { method: Method, headers: Headers, body: Option>, - startedDateTime: Tm + startedDateTime: Tm, + timeStamp: i64, + connect_time: u64, + send_time: u64, } struct HttpResponse { @@ -48,13 +51,14 @@ pub struct EventActor { pub url: String, pub method: String, pub startedDateTime: String, + pub timeStamp: i64, pub isXHR: bool, pub private: bool } #[derive(Serialize)] pub struct ResponseCookiesMsg { - pub cookies: u32, + pub cookies: usize, } #[derive(Serialize)] @@ -64,7 +68,7 @@ pub struct ResponseStartMsg { pub remotePort: u32, pub status: String, pub statusText: String, - pub headersSize: u32, + pub headersSize: usize, pub discardResponseBody: bool, } @@ -79,29 +83,41 @@ pub struct ResponseContentMsg { #[derive(Serialize)] pub struct ResponseHeadersMsg { - pub headers: u32, - pub headersSize: u32, + pub headers: usize, + pub headersSize: usize, } #[derive(Serialize)] pub struct RequestCookiesMsg { - pub cookies: u32, + pub cookies: usize, +} + +#[derive(Serialize)] +pub struct RequestHeadersMsg { + headers: usize, + headersSize: usize, } #[derive(Serialize)] struct GetRequestHeadersReply { from: String, - headers: Vec, - headerSize: u8, + headers: Vec
, + headerSize: usize, rawHeaders: String } +#[derive(Serialize)] +struct Header { + name: String, + value: String, +} + #[derive(Serialize)] struct GetResponseHeadersReply { from: String, - headers: Vec, - headerSize: u8, + headers: Vec
, + headerSize: usize, rawHeaders: String } @@ -135,8 +151,8 @@ struct GetResponseCookiesReply { struct Timings { blocked: u32, dns: u32, - connect: u32, - send: u32, + connect: u64, + send: u64, wait: u32, receive: u32, } @@ -145,16 +161,20 @@ struct Timings { struct GetEventTimingsReply { from: String, timings: Timings, - totalTime: u32, + totalTime: u64, +} + +#[derive(Serialize)] +struct SecurityInfo { + state: String, } #[derive(Serialize)] struct GetSecurityInfoReply { from: String, - seuritInfo: String, + securityInfo: SecurityInfo, } - impl Actor for NetworkEventActor { fn name(&self) -> String { self.name.clone() @@ -167,19 +187,19 @@ impl Actor for NetworkEventActor { stream: &mut TcpStream) -> Result { Ok(match msg_type { "getRequestHeaders" => { - // TODO: Pass the correct values for headers, headerSize, rawHeaders - let headersSize = self.request.headers.len() as u8; - let mut headerNames = Vec::new(); + let mut headers = Vec::new(); let mut rawHeadersString = "".to_owned(); + let mut headersSize = 0; for item in self.request.headers.iter() { let name = item.name(); let value = item.value_string(); - headerNames.push(name.to_owned()); rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n"; + headersSize += name.len() + value.len(); + headers.push(Header { name: name.to_owned(), value: value.to_owned() }); } let msg = GetRequestHeadersReply { from: self.name(), - headers: headerNames, + headers: headers, headerSize: headersSize, rawHeaders: rawHeadersString, }; @@ -213,25 +233,32 @@ impl Actor for NetworkEventActor { ActorMessageStatus::Processed } "getResponseHeaders" => { - if let Some(ref headers) = self.response.headers { - let headersSize = headers.len() as u8; - let mut headerNames = Vec::new(); + if let Some(ref response_headers) = self.response.headers { + let mut headers = vec![]; let mut rawHeadersString = "".to_owned(); - for item in headers.iter() { + let mut headersSize = 0; + for item in response_headers.iter() { let name = item.name(); let value = item.value_string(); - headerNames.push(name.to_owned()); - rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n"; + headers.push(Header { + name: name.to_owned(), + value: value.clone(), + }); + headersSize += name.len() + value.len(); + rawHeadersString.push_str(name); + rawHeadersString.push_str(":"); + rawHeadersString.push_str(&value); + rawHeadersString.push_str("\r\n"); } let msg = GetResponseHeadersReply { from: self.name(), - headers: headerNames, + headers: headers, headerSize: headersSize, rawHeaders: rawHeadersString, }; stream.write_json_packet(&msg); } - ActorMessageStatus::Processed + ActorMessageStatus::Processed } "getResponseCookies" => { let mut cookies = Vec::new(); @@ -254,7 +281,7 @@ impl Actor for NetworkEventActor { let msg = GetResponseContentReply { from: self.name(), content: self.response.body.clone(), - contentDiscarded: false, + contentDiscarded: self.response.body.is_none(), }; stream.write_json_packet(&msg); ActorMessageStatus::Processed @@ -264,16 +291,17 @@ impl Actor for NetworkEventActor { let timingsObj = Timings { blocked: 0, dns: 0, - connect: 0, - send: 0, + connect: self.request.connect_time, + send: self.request.send_time, wait: 0, receive: 0, }; + let total = timingsObj.connect + timingsObj.send; // TODO: Send the correct values for all these fields. let msg = GetEventTimingsReply { from: self.name(), timings: timingsObj, - totalTime: 0, + totalTime: total, }; stream.write_json_packet(&msg); ActorMessageStatus::Processed @@ -282,7 +310,9 @@ impl Actor for NetworkEventActor { // TODO: Send the correct values for securityInfo. let msg = GetSecurityInfoReply { from: self.name(), - seuritInfo: "".to_owned(), + securityInfo: SecurityInfo { + state: "insecure".to_owned() + }, }; stream.write_json_packet(&msg); ActorMessageStatus::Processed @@ -302,6 +332,9 @@ impl NetworkEventActor { headers: Headers::new(), body: None, startedDateTime: time::now(), + timeStamp: time::get_time().sec, + send_time: 0, + connect_time: 0, }, response: HttpResponse { headers: None, @@ -317,6 +350,9 @@ impl NetworkEventActor { self.request.headers = request.headers.clone(); self.request.body = request.body; self.request.startedDateTime = request.startedDateTime; + self.request.timeStamp = request.timeStamp; + self.request.connect_time = request.connect_time; + self.request.send_time = request.send_time; } pub fn add_response(&mut self, response: DevtoolsHttpResponse) { @@ -332,6 +368,7 @@ impl NetworkEventActor { url: self.request.url.clone(), method: format!("{}", self.request.method), startedDateTime: format!("{}", self.request.startedDateTime.rfc3339()), + timeStamp: self.request.timeStamp, isXHR: false, private: false, } @@ -339,7 +376,7 @@ impl NetworkEventActor { pub fn response_start(&self) -> ResponseStartMsg { // TODO: Send the correct values for all these fields. - let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len() as u32); + let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len()); let hSize = hSizeOption.unwrap_or(0); let (status_code, status_message) = self.response.status.as_ref(). map_or((0, "".to_owned()), |&RawStatus(ref code, ref text)| (*code, text.clone().into_owned())); @@ -368,7 +405,7 @@ impl NetworkEventActor { mimeType: mString, contentSize: 0, transferredSize: 0, - discardResponseBody: false, + discardResponseBody: true, } } @@ -381,7 +418,7 @@ impl NetworkEventActor { }; } ResponseCookiesMsg { - cookies: cookies_size as u32, + cookies: cookies_size, } } @@ -389,7 +426,7 @@ impl NetworkEventActor { let mut headers_size = 0; let mut headers_byte_count = 0; if let Some(ref headers) = self.response.headers { - headers_size = headers.len() as u32; + headers_size = headers.len(); for item in headers.iter() { headers_byte_count += item.name().len() + item.value_string().len(); } @@ -397,21 +434,32 @@ impl NetworkEventActor { } ResponseHeadersMsg { headers: headers_size, - headersSize: headers_byte_count as u32, + headersSize: headers_byte_count, + } + } + + pub fn request_headers(&self) -> RequestHeadersMsg { + let size = self.request + .headers + .iter() + .fold(0, |acc, h| acc + h.name().len() + h.value_string().len()); + RequestHeadersMsg { + headers: self.request.headers.len(), + headersSize: size, } } pub fn request_cookies(&self) -> RequestCookiesMsg { - let mut cookies_size = 0; - if let Some(ref headers) = self.response.headers { - cookies_size = match headers.get() { - Some(&Cookie(ref cookie)) => cookie.len(), - None => 0 - }; - } + let cookies_size = match self.request.headers.get() { + Some(&Cookie(ref cookie)) => cookie.len(), + None => 0 + }; RequestCookiesMsg { - cookies: cookies_size as u32, + cookies: cookies_size, } } + pub fn total_time(&self) -> u64 { + self.request.connect_time + self.request.send_time + } } diff --git a/components/devtools/actors/root.rs b/components/devtools/actors/root.rs index 6103e5a9a4f..1885e775ff6 100644 --- a/components/devtools/actors/root.rs +++ b/components/devtools/actors/root.rs @@ -19,7 +19,8 @@ use std::net::TcpStream; struct ActorTraits { sources: bool, highlightable: bool, - customHighlighters: Vec, + customHighlighters: bool, + networkMonitor: bool, } #[derive(Serialize)] @@ -117,7 +118,8 @@ impl RootActor { traits: ActorTraits { sources: true, highlightable: true, - customHighlighters: vec!("BoxModelHighlighter".to_owned()), + customHighlighters: true, + networkMonitor: true }, } } diff --git a/components/devtools/actors/tab.rs b/components/devtools/actors/tab.rs index 51694c9aa7a..fd93553e6b7 100644 --- a/components/devtools/actors/tab.rs +++ b/components/devtools/actors/tab.rs @@ -9,7 +9,7 @@ use actor::{Actor, ActorMessageStatus, ActorRegistry}; use actors::console::ConsoleActor; -use devtools_traits::DevtoolScriptControlMsg::WantsLiveNotifications; +use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications}; use protocol::JsonPacketStream; use serde_json::Value; use std::collections::BTreeMap; @@ -88,10 +88,19 @@ impl Actor for TabActor { fn handle_message(&self, registry: &ActorRegistry, msg_type: &str, - _msg: &BTreeMap, + msg: &BTreeMap, stream: &mut TcpStream) -> Result { Ok(match msg_type { "reconfigure" => { + if let Some(options) = msg.get("options").and_then(|o| o.as_object()) { + if let Some(val) = options.get("performReload") { + if val.as_boolean().unwrap_or(false) { + let console_actor = registry.find::(&self.console); + let _ = console_actor.script_chan.send( + DevtoolScriptControlMsg::Reload(console_actor.pipeline)); + } + } + } stream.write_json_packet(&ReconfigureReply { from: self.name() }); ActorMessageStatus::Processed } diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index a0d514f9025..42f5ce86a02 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -35,8 +35,7 @@ use actor::{Actor, ActorRegistry}; use actors::console::ConsoleActor; use actors::framerate::FramerateActor; use actors::inspector::InspectorActor; -use actors::network_event::{EventActor, NetworkEventActor, RequestCookiesMsg, ResponseCookiesMsg }; -use actors::network_event::{ResponseContentMsg, ResponseHeadersMsg, ResponseStartMsg }; +use actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg}; use actors::performance::PerformanceActor; use actors::profiler::ProfilerActor; use actors::root::RootActor; @@ -105,6 +104,24 @@ struct NetworkEventMsg { eventActor: EventActor, } +#[derive(Serialize)] +struct NetworkEventUpdateMsg { + from: String, + #[serde(rename = "type")] + type_: String, + updateType: String, +} + +#[derive(Serialize)] +struct EventTimingsUpdateMsg { + totalTime: u64, +} + +#[derive(Serialize)] +struct SecurityInfoUpdateMsg { + state: String, +} + #[derive(Serialize)] struct ResponseStartUpdateMsg { from: String, @@ -114,60 +131,6 @@ struct ResponseStartUpdateMsg { response: ResponseStartMsg, } -#[derive(Serialize)] -struct ResponseContentUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - responseContent: ResponseContentMsg, -} - -#[derive(Serialize)] -struct ResponseCookiesUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - responseCookies: ResponseCookiesMsg, -} - -#[derive(Serialize)] -struct ResponseHeadersUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - responseHeaders: ResponseHeadersMsg, -} - -#[derive(Serialize)] -struct RequestCookiesUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - requestcookies: RequestCookiesMsg, -} - -#[derive(Serialize)] -struct EventTimingsUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - totalTime: u32, -} - -#[derive(Serialize)] -struct SecurityInfoUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - securityState: String, -} - /// Spin up a devtools server that listens for connections on the specified port. pub fn start_server(port: u16) -> Sender { let (sender, receiver) = channel(); @@ -416,14 +379,22 @@ fn run_server(sender: Sender, //Store the response information in the actor actor.add_response(httpresponse); - let msg7 = RequestCookiesUpdateMsg { + let msg = NetworkEventUpdateMsg { + from: netevent_actor_name.clone(), + type_: "networkEventUpdate".to_owned(), + updateType: "requestHeaders".to_owned(), + }; + for stream in &mut connections { + stream.write_merged_json_packet(&msg, &actor.request_headers()); + } + + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "requestCookies".to_owned(), - requestcookies: actor.request_cookies(), }; for stream in &mut connections { - stream.write_json_packet(&msg7); + stream.write_merged_json_packet(&msg, &actor.request_cookies()); } //Send a networkEventUpdate (responseStart) to the client @@ -437,61 +408,56 @@ fn run_server(sender: Sender, for stream in &mut connections { stream.write_json_packet(&msg); } - let msg2 = EventTimingsUpdateMsg { + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "eventTimings".to_owned(), - totalTime: 0 }; - + let extra = EventTimingsUpdateMsg { + totalTime: actor.total_time(), + }; for stream in &mut connections { - stream.write_json_packet(&msg2); + stream.write_merged_json_packet(&msg, &extra); } - let msg3 = SecurityInfoUpdateMsg { + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "securityInfo".to_owned(), - securityState: "".to_owned(), }; - + let extra = SecurityInfoUpdateMsg { + state: "insecure".to_owned(), + }; for stream in &mut connections { - stream.write_json_packet(&msg3); + stream.write_merged_json_packet(&msg, &extra); } - let msg4 = ResponseContentUpdateMsg { + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "responseContent".to_owned(), - responseContent: actor.response_content(), }; - for stream in &mut connections { - stream.write_json_packet(&msg4); + stream.write_merged_json_packet(&msg, &actor.response_content()); } - let msg5 = ResponseCookiesUpdateMsg { + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "responseCookies".to_owned(), - responseCookies: actor.response_cookies(), }; - for stream in &mut connections { - stream.write_json_packet(&msg5); + stream.write_merged_json_packet(&msg, &actor.response_cookies()); } - let msg6 = ResponseHeadersUpdateMsg { + let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), type_: "networkEventUpdate".to_owned(), updateType: "responseHeaders".to_owned(), - responseHeaders: actor.response_headers(), }; - for stream in &mut connections { - stream.write_json_packet(&msg6); + stream.write_merged_json_packet(&msg, &actor.response_headers()); } - } } } diff --git a/components/devtools/protocol.rs b/components/devtools/protocol.rs index 3da44cc5323..b385f396c1b 100644 --- a/components/devtools/protocol.rs +++ b/components/devtools/protocol.rs @@ -28,6 +28,7 @@ pub struct Method { pub trait JsonPacketStream { fn write_json_packet(&mut self, obj: &T); + fn write_merged_json_packet(&mut self, base: &T, extra: &U); fn read_json_packet(&mut self) -> Result, String>; } @@ -38,6 +39,19 @@ impl JsonPacketStream for TcpStream { write!(self, "{}:{}", s.len(), s).unwrap(); } + fn write_merged_json_packet(&mut self, base: &T, extra: &U) { + let mut obj = serde_json::to_value(base); + let obj = obj.as_object_mut().unwrap(); + let extra = serde_json::to_value(extra); + let extra = extra.as_object().unwrap(); + + for (key, value) in extra { + obj.insert(key.to_owned(), value.to_owned()); + } + + self.write_json_packet(obj); + } + fn read_json_packet(&mut self) -> Result, String> { // https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport // In short, each JSON packet is [ascii length]:[JSON data of given length] diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index 381af6016b3..d64ac04b16f 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -214,6 +214,8 @@ pub enum DevtoolScriptControlMsg { /// Request a callback directed at the given actor name from the next animation frame /// executed in the given pipeline. RequestAnimationFrame(PipelineId, String), + /// Direct the given pipeline to reload the current page. + Reload(PipelineId), } #[derive(Deserialize, Serialize)] @@ -292,7 +294,10 @@ pub struct HttpRequest { pub headers: Headers, pub body: Option>, pub pipeline_id: PipelineId, - pub startedDateTime: Tm + pub startedDateTime: Tm, + pub timeStamp: i64, + pub connect_time: u64, + pub send_time: u64, } #[derive(Debug, PartialEq)] diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 45ecbd1e603..16d64a86a7c 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -816,7 +816,7 @@ fn http_network_fetch(request: Rc, let mut response = Response::new(); match wrapped_response { - Ok(mut res) => { + Ok((mut res, _)) => { response.url = Some(res.response.url.clone()); response.status = Some(res.response.status); response.headers = res.response.headers.clone(); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index a6b810cc18a..f9fc6224d36 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -119,6 +119,10 @@ impl HttpState { } } +fn precise_time_ms() -> u64 { + time::precise_time_ns() / (1000 * 1000) +} + fn load_for_consumer(load_data: LoadData, start_chan: LoadConsumer, classifier: Arc, @@ -552,21 +556,34 @@ enum Decoder { Plain(Box) } -fn send_request_to_devtools(devtools_chan: Option>, - request_id: String, +fn prepare_devtools_request(request_id: String, url: Url, method: Method, headers: Headers, body: Option>, - pipeline_id: PipelineId, now: Tm) { - if let Some(ref chan) = devtools_chan { - let request = DevtoolsHttpRequest { - url: url, method: method, headers: headers, body: body, pipeline_id: pipeline_id, startedDateTime: now }; - let net_event = NetworkEvent::HttpRequest(request); + pipeline_id: PipelineId, + now: Tm, + connect_time: u64, + send_time: u64) -> ChromeToDevtoolsControlMsg { + let request = DevtoolsHttpRequest { + url: url, + method: method, + headers: headers, + body: body, + pipeline_id: pipeline_id, + startedDateTime: now, + timeStamp: now.to_timespec().sec, + connect_time: connect_time, + send_time: send_time, + }; + let net_event = NetworkEvent::HttpRequest(request); - let msg = ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event); - chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap(); - } + ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event) +} + +fn send_request_to_devtools(msg: ChromeToDevtoolsControlMsg, + devtools_chan: &Sender) { + devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap(); } fn send_response_to_devtools(devtools_chan: Option>, @@ -701,10 +718,12 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, iters: u32, devtools_chan: &Option>, request_id: &str) - -> Result where A: HttpRequest + 'static { + -> Result<(A::R, Option), LoadError> + where A: HttpRequest + 'static { let null_data = None; let response; let connection_url = replace_hosts(&url); + let mut msg; // loop trying connections in connection pool // they may have grown stale (disconnected), in which case we'll get @@ -742,22 +761,36 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, info!("{:?}", data); } + let connect_start = precise_time_ms(); + let req = try!(request_factory.create(connection_url.clone(), method.clone(), headers.clone())); + let connect_end = precise_time_ms(); + if cancel_listener.is_cancelled() { return Err(LoadError::new(connection_url.clone(), LoadErrorType::Cancelled)); } + let send_start = precise_time_ms(); + let maybe_response = req.send(request_body); - if let Some(pipeline_id) = *pipeline_id { - send_request_to_devtools( - devtools_chan.clone(), request_id.clone().into(), - url.clone(), method.clone(), headers, - request_body.clone(), pipeline_id, time::now() - ); - } + let send_end = precise_time_ms(); + + msg = if devtools_chan.is_some() { + if let Some(pipeline_id) = *pipeline_id { + Some(prepare_devtools_request( + request_id.clone().into(), + url.clone(), method.clone(), headers, + request_body.clone(), pipeline_id, time::now(), + connect_end - connect_start, send_end - send_start)) + } else { + None + } + } else { + None + }; response = match maybe_response { Ok(r) => r, @@ -775,7 +808,7 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, break; } - Ok(response) + Ok((response, msg)) } pub trait UIProvider { @@ -914,9 +947,10 @@ pub fn load(load_data: &LoadData, request_headers.set(auth_header.clone()); } - let response = try!(obtain_response(request_factory, &doc_url, &method, &request_headers, - &cancel_listener, &load_data.data, &load_data.method, - &load_data.pipeline_id, iters, &devtools_chan, &request_id)); + let (response, msg) = + try!(obtain_response(request_factory, &doc_url, &method, &request_headers, + &cancel_listener, &load_data.data, &load_data.method, + &load_data.pipeline_id, iters, &devtools_chan, &request_id)); process_response_headers(&response, &doc_url, &http_state.cookie_jar, &http_state.hsts_list, &load_data); @@ -1006,6 +1040,11 @@ pub fn load(load_data: &LoadData, HttpsState::None }; + // Only notify the devtools about the final request that received a response. + if let Some(msg) = msg { + send_request_to_devtools(msg, devtools_chan.as_ref().unwrap()); + } + // --- Tell devtools that we got a response // Send an HttpResponse message to devtools with the corresponding request_id // TODO: Send this message even when the load fails? diff --git a/components/script/devtools.rs b/components/script/devtools.rs index 8f783126a62..7533b159771 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -10,6 +10,7 @@ use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclar use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; +use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::{FromJSValConvertible, jsstring_to_str}; use dom::bindings::global::GlobalRef; @@ -250,3 +251,11 @@ pub fn handle_request_animation_frame(context: &BrowsingContext, devtools_sender.send(msg).unwrap(); }); } + +pub fn handle_reload(context: &BrowsingContext, + id: PipelineId) { + let context = context.find(id).expect("There is no such context"); + let win = context.active_window(); + let location = win.Location(); + location.Reload(); +} diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 35ae783f5ff..22c46840445 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1021,6 +1021,8 @@ impl ScriptThread { devtools::handle_drop_timeline_markers(&context, marker_types), DevtoolScriptControlMsg::RequestAnimationFrame(pipeline_id, name) => devtools::handle_request_animation_frame(&context, pipeline_id, name), + DevtoolScriptControlMsg::Reload(pipeline_id) => + devtools::handle_reload(&context, pipeline_id), } } diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index ba1a7d6f2b0..e414f2f39f2 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -503,7 +503,10 @@ fn test_request_and_response_data_with_network_messages() { headers: headers, body: None, pipeline_id: pipeline_id, - startedDateTime: devhttprequest.startedDateTime + startedDateTime: devhttprequest.startedDateTime, + timeStamp: devhttprequest.timeStamp, + connect_time: devhttprequest.connect_time, + send_time: devhttprequest.send_time, }; let content = "Yay!";