From 9c9d7dc93b1d64b1524eb2bdcbdc817319abc8b9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 9 Jul 2015 16:18:38 -0700 Subject: [PATCH 1/5] net: Make most of the resource task messages serializable. --- components/layout/layout_task.rs | 2 +- components/net/about_loader.rs | 18 +- components/net/data_loader.rs | 20 +- components/net/file_loader.rs | 12 +- components/net/http_loader.rs | 45 +-- components/net/image_cache_task.rs | 4 +- components/net/resource_task.rs | 15 +- components/net_traits/lib.rs | 295 ++++++++++++++++-- components/script/cors.rs | 4 +- .../script/dom/dedicatedworkerglobalscope.rs | 4 +- components/script/dom/document.rs | 10 +- components/script/dom/htmlscriptelement.rs | 2 +- components/script/dom/servohtmlparser.rs | 2 +- components/script/dom/xmlhttprequest.rs | 25 +- components/script/script_task.rs | 20 +- 15 files changed, 373 insertions(+), 105 deletions(-) diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 001f8f42d2a..12a2b549c38 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -718,7 +718,7 @@ impl LayoutTask { // TODO we don't really even need to load this if mq does not match let (metadata, iter) = load_bytes_iter(pending); let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url; + let final_url = metadata.final_url.0; let sheet = Stylesheet::from_bytes_iter(iter, final_url, diff --git a/components/net/about_loader.rs b/components/net/about_loader.rs index 213988904c2..d20a3e4ef63 100644 --- a/components/net/about_loader.rs +++ b/components/net/about_loader.rs @@ -2,7 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer}; +use net_traits::{LoadData, Metadata, LoadConsumer, SerializableContentType, SerializableRawStatus}; +use net_traits::{SerializableStringResult, SerializableUrl}; use net_traits::ProgressMsg::Done; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -22,12 +23,14 @@ pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Ar "blank" => { let chan = start_sending(start_chan, Metadata { final_url: load_data.url, - content_type: Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))), + content_type: Some(SerializableContentType(ContentType(Mime(TopLevel::Text, + SubLevel::Html, + vec![])))), charset: Some("utf-8".to_string()), headers: None, - status: Some(RawStatus(200, "OK".into())), + status: Some(SerializableRawStatus(RawStatus(200, "OK".into()))), }); - chan.send(Done(Ok(()))).unwrap(); + chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); return } "crash" => panic!("Loading the about:crash URL."), @@ -35,11 +38,12 @@ pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Ar let mut path = resources_dir_path(); path.push("failure.html"); assert!(path.exists()); - load_data.url = Url::from_file_path(&*path).unwrap(); + load_data.url = SerializableUrl(Url::from_file_path(&*path).unwrap()); } _ => { - start_sending(start_chan, Metadata::default(load_data.url)) - .send(Done(Err("Unknown about: URL.".to_string()))).unwrap(); + start_sending(start_chan, Metadata::default(load_data.url.0)) + .send(Done(SerializableStringResult(Err("Unknown about: URL.".to_string())))) + .unwrap(); return } }; diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs index 36daf044e61..f1f99d6efe2 100644 --- a/components/net/data_loader.rs +++ b/components/net/data_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer}; +use net_traits::{LoadData, Metadata, LoadConsumer, SerializableStringResult}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -26,23 +26,24 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) { let url = load_data.url; assert!(&*url.scheme == "data"); - let mut metadata = Metadata::default(url.clone()); + let mut metadata = Metadata::default((*url).clone()); // Split out content type and data. let mut scheme_data = match url.scheme_data { - SchemeData::NonRelative(scheme_data) => scheme_data, + SchemeData::NonRelative(ref scheme_data) => (*scheme_data).clone(), _ => panic!("Expected a non-relative scheme URL.") }; match url.query { - Some(query) => { + Some(ref query) => { scheme_data.push_str("?"); - scheme_data.push_str(&query); + scheme_data.push_str(query); }, None => () } let parts: Vec<&str> = scheme_data.splitn(2, ',').collect(); if parts.len() != 2 { - start_sending(start_chan, metadata).send(Done(Err("invalid data uri".to_string()))).unwrap(); + start_sending(start_chan, metadata).send(Done(SerializableStringResult(Err( + "invalid data uri".to_string())))).unwrap(); return; } @@ -69,15 +70,16 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) { let bytes = bytes.into_iter().filter(|&b| b != ' ' as u8).collect::>(); match bytes.from_base64() { Err(..) => { - progress_chan.send(Done(Err("non-base64 data uri".to_string()))).unwrap(); + progress_chan.send(Done(SerializableStringResult(Err( + "non-base64 data uri".to_string())))).unwrap(); } Ok(data) => { progress_chan.send(Payload(data)).unwrap(); - progress_chan.send(Done(Ok(()))).unwrap(); + progress_chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); } } } else { progress_chan.send(Payload(bytes)).unwrap(); - progress_chan.send(Done(Ok(()))).unwrap(); + progress_chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); } } diff --git a/components/net/file_loader.rs b/components/net/file_loader.rs index a81d0e8afdb..08de3298cf3 100644 --- a/components/net/file_loader.rs +++ b/components/net/file_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer}; +use net_traits::{LoadData, Metadata, LoadConsumer, SerializableStringResult}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::{start_sending, start_sending_sniffed, ProgressSender}; @@ -48,7 +48,7 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc = url.to_file_path(); match file_path { Ok(file_path) => { @@ -65,17 +65,19 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc (res.map(|_| ()), start_sending(senders, metadata)), }; - progress_chan.send(Done(res)).unwrap(); + progress_chan.send(Done(SerializableStringResult(res))).unwrap(); } Err(e) => { let progress_chan = start_sending(senders, metadata); - progress_chan.send(Done(Err(e.description().to_string()))).unwrap(); + progress_chan.send(Done(SerializableStringResult(Err(e.description() + .to_string())))) + .unwrap(); } } } Err(_) => { let progress_chan = start_sending(senders, metadata); - progress_chan.send(Done(Err(url.to_string()))).unwrap(); + progress_chan.send(Done(SerializableStringResult(Err(url.to_string())))).unwrap(); } } }); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 637558a4e7f..cc186787985 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -2,7 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer}; +use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, SerializableMethod}; +use net_traits::{SerializableHeaders, SerializableRawStatus, SerializableStringResult}; +use net_traits::{SerializableUrl}; use net_traits::ProgressMsg::{Payload, Done}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent}; use mime_classifier::MIMEClassifier; @@ -51,7 +53,7 @@ fn send_error(url: Url, err: String, start_chan: LoadConsumer) { metadata.status = None; match start_sending_opt(start_chan, metadata) { - Ok(p) => p.send(Done(Err(err))).unwrap(), + Ok(p) => p.send(Done(SerializableStringResult(Err(err)))).unwrap(), _ => {} }; } @@ -94,7 +96,7 @@ fn load(mut load_data: LoadData, // repository DOES exist, please update this constant to use it. let max_redirects = 50; let mut iters = 0; - let mut url = load_data.url.clone(); + let mut url = load_data.url.0.clone(); let mut redirected_to = HashSet::new(); // If the URL is a view-source scheme then the scheme data contains the @@ -153,7 +155,10 @@ reason: \"certificate verify failed\" }]))"; Request::with_connector(load_data.method.clone(), url.clone(), &HttpsConnector::new(Openssl { context: Arc::new(context) })) }; - let mut req = match req { + + let mut req = match Request::with_connector(load_data.method.0.clone(), + url.clone(), + &mut connector) { Ok(req) => req, Err(HttpError::Io(ref io_error)) if ( io_error.kind() == io::ErrorKind::Other && @@ -182,11 +187,11 @@ reason: \"certificate verify failed\" }]))"; // https://bugzilla.mozilla.org/show_bug.cgi?id=216828 . // Only preserve ones which have been explicitly marked as such. if iters == 1 { - let mut combined_headers = load_data.headers.clone(); + let mut combined_headers = (*load_data.headers).clone(); combined_headers.extend(load_data.preserved_headers.iter()); *req.headers_mut() = combined_headers; } else { - *req.headers_mut() = load_data.preserved_headers.clone(); + *req.headers_mut() = (*load_data.preserved_headers).clone(); } req.headers_mut().set(host); @@ -202,7 +207,9 @@ reason: \"certificate verify failed\" }]))"; } let (tx, rx) = channel(); - cookies_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), tx, CookieSource::HTTP)).unwrap(); + cookies_chan.send(ControlMsg::GetCookiesForUrl(SerializableUrl(url.clone()), + tx, + CookieSource::HTTP)).unwrap(); if let Some(cookie_list) = rx.recv().unwrap() { let mut v = Vec::new(); v.push(cookie_list.into_bytes()); @@ -213,7 +220,7 @@ reason: \"certificate verify failed\" }]))"; req.headers_mut().set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]); } if log_enabled!(log::LogLevel::Info) { - info!("{}", load_data.method); + info!("{}", load_data.method.0); for header in req.headers().iter() { info!(" - {}", header); } @@ -241,7 +248,7 @@ reason: \"certificate verify failed\" }]))"; writer }, _ => { - match load_data.method { + match *load_data.method { Method::Get | Method::Head => (), _ => req.headers_mut().set(ContentLength(0)) } @@ -259,9 +266,9 @@ reason: \"certificate verify failed\" }]))"; // TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id in the message let request_id = uuid::Uuid::new_v4().to_simple_string(); if let Some(ref chan) = devtools_chan { - let net_event = NetworkEvent::HttpRequest(load_data.url.clone(), - load_data.method.clone(), - load_data.headers.clone(), + let net_event = NetworkEvent::HttpRequest((*load_data.url).clone(), + (*load_data.method).clone(), + (*load_data.headers).clone(), load_data.data.clone()); chan.send(DevtoolsControlMsg::FromChrome( ChromeToDevtoolsControlMsg::NetworkEventMessage(request_id.clone(), @@ -287,7 +294,7 @@ reason: \"certificate verify failed\" }]))"; if let Some(cookies) = response.headers.get_raw("set-cookie") { for cookie in cookies.iter() { if let Ok(cookies) = String::from_utf8(cookie.clone()) { - cookies_chan.send(ControlMsg::SetCookiesForUrl(url.clone(), + cookies_chan.send(ControlMsg::SetCookiesForUrl(SerializableUrl(url.clone()), cookies, CookieSource::HTTP)).unwrap(); } @@ -325,10 +332,10 @@ reason: \"certificate verify failed\" }]))"; // According to https://tools.ietf.org/html/rfc7231#section-6.4.2, // historically UAs have rewritten POST->GET on 301 and 302 responses. - if load_data.method == Method::Post && + if *load_data.method == Method::Post && (response.status == StatusCode::MovedPermanently || response.status == StatusCode::Found) { - load_data.method = Method::Get; + load_data.method = SerializableMethod(Method::Get); } if redirected_to.contains(&url) { @@ -352,8 +359,8 @@ reason: \"certificate verify failed\" }]))"; Some(&ContentType(ref mime)) => Some(mime), None => None }); - metadata.headers = Some(adjusted_headers); - metadata.status = Some(response.status_raw().clone()); + metadata.headers = Some(SerializableHeaders(adjusted_headers)); + metadata.status = Some(SerializableRawStatus(response.status_raw().clone())); let mut encoding_str: Option = None; //FIXME: Implement Content-Encoding Header https://github.com/hyperium/hyper/issues/391 @@ -389,7 +396,7 @@ reason: \"certificate verify failed\" }]))"; send_data(&mut response_decoding, start_chan, metadata, classifier); } Err(err) => { - send_error(metadata.final_url, err.to_string(), start_chan); + send_error((*metadata.final_url).clone(), err.to_string(), start_chan); return; } } @@ -438,5 +445,5 @@ fn send_data(reader: &mut R, }; } - let _ = progress_chan.send(Done(Ok(()))); + let _ = progress_chan.send(Done(SerializableStringResult(Ok(())))); } diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs index e6088051c29..865e8c6e37b 100644 --- a/components/net/image_cache_task.rs +++ b/components/net/image_cache_task.rs @@ -248,10 +248,10 @@ impl ImageCache { pending_load.bytes.push_all(&data); } ResponseAction::ResponseComplete(result) => { - match result { + match *result { Ok(()) => { let pending_load = self.pending_loads.get_mut(&msg.url).unwrap(); - pending_load.result = Some(result); + pending_load.result = Some((*result).clone()); let bytes = mem::replace(&mut pending_load.bytes, vec!()); let url = msg.url.clone(); diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index 1e857102e33..d206e252c93 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -13,7 +13,8 @@ use cookie; use mime_classifier::MIMEClassifier; use net_traits::{ControlMsg, LoadData, LoadResponse, LoadConsumer}; -use net_traits::{Metadata, ProgressMsg, ResourceTask, AsyncResponseTarget, ResponseAction, CookieSource}; +use net_traits::{Metadata, ProgressMsg, ResourceTask, AsyncResponseTarget, ResponseAction}; +use net_traits::{CookieSource, SerializableContentType, SerializableStringResult}; use net_traits::ProgressMsg::Done; use util::opts; use util::task::spawn_named; @@ -124,14 +125,17 @@ pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadat } } - let supplied_type = metadata.content_type.map(|ContentType(Mime(toplevel, sublevel, _))| { + let supplied_type = + metadata.content_type.map(|SerializableContentType(ContentType(Mime(toplevel, + sublevel, + _)))| { (format!("{}", toplevel), format!("{}", sublevel)) }); metadata.content_type = classifier.classify(nosniff, check_for_apache_bug, &supplied_type, &partial_body).map(|(toplevel, sublevel)| { let mime_tp: TopLevel = toplevel.parse().unwrap(); let mime_sb: SubLevel = sublevel.parse().unwrap(); - ContentType(Mime(mime_tp, mime_sb, vec!())) + SerializableContentType(ContentType(Mime(mime_tp, mime_sb, vec!()))) }); } @@ -321,8 +325,9 @@ impl ResourceManager { "about" => from_factory(about_loader::factory), _ => { debug!("resource_task: no loader for scheme {}", load_data.url.scheme); - start_sending(consumer, Metadata::default(load_data.url)) - .send(ProgressMsg::Done(Err("no loader for scheme".to_string()))).unwrap(); + start_sending(consumer, Metadata::default((*load_data.url).clone())) + .send(ProgressMsg::Done(SerializableStringResult(Err( + "no loader for scheme".to_string())))).unwrap(); return } }; diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 0028c61dcce..8e243195cf6 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -10,8 +10,6 @@ #![feature(vec_push_all)] #![plugin(serde_macros)] -#![plugin(serde_macros)] - extern crate euclid; extern crate hyper; extern crate ipc_channel; @@ -24,13 +22,19 @@ extern crate url; extern crate util; extern crate msg; -use hyper::header::{ContentType, Headers}; +use hyper::header::{ContentType, Header, Headers, HeadersItems}; use hyper::http::RawStatus; use hyper::method::Method; use hyper::mime::{Mime, Attr}; use msg::constellation_msg::{PipelineId}; +use serde::de; +use serde::ser; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use url::Url; +use std::borrow::Cow; +use std::ops::{Deref, DerefMut}; +use std::str::FromStr; use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; @@ -46,14 +50,14 @@ pub mod image { pub mod base; } -#[derive(Clone)] +#[derive(Clone, Deserialize, Serialize)] pub struct LoadData { - pub url: Url, - pub method: Method, + pub url: SerializableUrl, + pub method: SerializableMethod, /// Headers that will apply to the initial request only - pub headers: Headers, + pub headers: SerializableHeaders, /// Headers that will apply to the initial request and any redirects - pub preserved_headers: Headers, + pub preserved_headers: SerializableHeaders, pub data: Option>, pub cors: Option, pub pipeline_id: Option, @@ -62,10 +66,10 @@ pub struct LoadData { impl LoadData { pub fn new(url: Url, id: Option) -> LoadData { LoadData { - url: url, - method: Method::Get, - headers: Headers::new(), - preserved_headers: Headers::new(), + url: SerializableUrl(url), + method: SerializableMethod(Method::Get), + headers: SerializableHeaders(Headers::new()), + preserved_headers: SerializableHeaders(Headers::new()), data: None, cors: None, pipeline_id: id, @@ -87,13 +91,14 @@ pub trait AsyncResponseListener { /// Data for passing between threads/processes to indicate a particular action to /// take on a provided network listener. +#[derive(Deserialize, Serialize)] pub enum ResponseAction { /// Invoke headers_available HeadersAvailable(Metadata), /// Invoke data_available DataAvailable(Vec), /// Invoke response_complete - ResponseComplete(Result<(), String>) + ResponseComplete(SerializableStringResult) } impl ResponseAction { @@ -102,7 +107,7 @@ impl ResponseAction { match self { ResponseAction::HeadersAvailable(m) => listener.headers_available(m), ResponseAction::DataAvailable(d) => listener.data_available(d), - ResponseAction::ResponseComplete(r) => listener.response_complete(r), + ResponseAction::ResponseComplete(r) => listener.response_complete(r.0), } } } @@ -132,9 +137,9 @@ pub enum ControlMsg { /// Request the data associated with a particular URL Load(LoadData, LoadConsumer), /// Store a set of cookies for a given originating URL - SetCookiesForUrl(Url, String, CookieSource), + SetCookiesForUrl(SerializableUrl, String, CookieSource), /// Retrieve the stored cookies for a given URL - GetCookiesForUrl(Url, Sender>, CookieSource), + GetCookiesForUrl(SerializableUrl, Sender>, CookieSource), /// Store a domain's STS information SetHSTSEntryForHost(String, IncludeSubdomains, Option), Exit @@ -210,43 +215,43 @@ pub struct LoadResponse { pub progress_port: Receiver, } -#[derive(Clone)] +#[derive(Clone, Deserialize, Serialize)] pub struct ResourceCORSData { /// CORS Preflight flag pub preflight: bool, /// Origin of CORS Request - pub origin: Url + pub origin: SerializableUrl, } /// Metadata about a loaded resource, such as is obtained from HTTP headers. -#[derive(Clone)] +#[derive(Clone, Deserialize, Serialize)] pub struct Metadata { /// Final URL after redirects. - pub final_url: Url, + pub final_url: SerializableUrl, /// MIME type / subtype. - pub content_type: Option<(ContentType)>, + pub content_type: Option<(SerializableContentType)>, /// Character set. pub charset: Option, /// Headers - pub headers: Option, + pub headers: Option, /// HTTP Status - pub status: Option, + pub status: Option, } impl Metadata { /// Metadata with defaults for everything optional. pub fn default(url: Url) -> Self { Metadata { - final_url: url, + final_url: SerializableUrl(url), content_type: None, charset: None, headers: None, // https://fetch.spec.whatwg.org/#concept-response-status-message - status: Some(RawStatus(200, "OK".into())), + status: Some(SerializableRawStatus(RawStatus(200, "OK".into()))), } } @@ -255,7 +260,7 @@ impl Metadata { match content_type { None => (), Some(mime) => { - self.content_type = Some(ContentType(mime.clone())); + self.content_type = Some(SerializableContentType(ContentType(mime.clone()))); let &Mime(_, _, ref parameters) = mime; for &(ref k, ref v) in parameters.iter() { if &Attr::Charset == k { @@ -268,7 +273,7 @@ impl Metadata { } /// The creator of a given cookie -#[derive(PartialEq, Copy, Clone)] +#[derive(PartialEq, Copy, Clone, Deserialize, Serialize)] pub enum CookieSource { /// An HTTP API HTTP, @@ -277,12 +282,12 @@ pub enum CookieSource { } /// Messages sent in response to a `Load` message -#[derive(PartialEq,Debug)] +#[derive(PartialEq, Debug, Deserialize, Serialize)] pub enum ProgressMsg { /// Binary data - there may be multiple of these Payload(Vec), /// Indicates loading is complete, either successfully or not - Done(Result<(), String>) + Done(SerializableStringResult) } /// Convenience function for synchronously loading a whole resource. @@ -296,8 +301,10 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) loop { match response.progress_port.recv().unwrap() { ProgressMsg::Payload(data) => buf.push_all(&data), - ProgressMsg::Done(Ok(())) => return Ok((response.metadata, buf)), - ProgressMsg::Done(Err(e)) => return Err(e) + ProgressMsg::Done(SerializableStringResult(Ok(()))) => { + return Ok((response.metadata, buf)) + } + ProgressMsg::Done(SerializableStringResult(Err(e))) => return Err(e) } } } @@ -321,8 +328,8 @@ impl Iterator for ProgressMsgPortIterator { fn next(&mut self) -> Option> { match self.progress_port.recv().unwrap() { ProgressMsg::Payload(data) => Some(data), - ProgressMsg::Done(Ok(())) => None, - ProgressMsg::Done(Err(e)) => { + ProgressMsg::Done(SerializableStringResult(Ok(()))) => None, + ProgressMsg::Done(SerializableStringResult(Err(e))) => { error!("error receiving bytes: {}", e); None } @@ -330,4 +337,226 @@ impl Iterator for ProgressMsgPortIterator { } } +#[derive(Clone)] +pub struct SerializableMethod(pub Method); + +impl Deref for SerializableMethod { + type Target = Method; + + fn deref(&self) -> &Method { + &self.0 + } +} + +impl Serialize for SerializableMethod { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + format!("{}", self.0).serialize(serializer) + } +} + +impl Deserialize for SerializableMethod { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let string_representation: String = try!(Deserialize::deserialize(deserializer)); + Ok(SerializableMethod(FromStr::from_str(&string_representation[..]).unwrap())) + } +} + +#[derive(Clone)] +pub struct SerializableHeaders(pub Headers); + +impl Deref for SerializableHeaders { + type Target = Headers; + + fn deref(&self) -> &Headers { + &self.0 + } +} + +impl DerefMut for SerializableHeaders { + fn deref_mut(&mut self) -> &mut Headers { + &mut self.0 + } +} + +impl Serialize for SerializableHeaders { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + struct HeadersVisitor<'a> { + iter: HeadersItems<'a>, + len: usize, + } + + impl<'a> ser::MapVisitor for HeadersVisitor<'a> { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> + where S: Serializer { + match self.iter.next() { + Some(header_item) => { + try!(serializer.visit_map_elt(header_item.name(), + header_item.value_string())); + Ok(Some(())) + } + None => Ok(None), + } + } + + fn len(&self) -> Option { + Some(self.len) + } + } + + serializer.visit_map(HeadersVisitor { + iter: self.iter(), + len: self.len(), + }) + } +} + +impl Deserialize for SerializableHeaders { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + struct HeadersVisitor; + + impl de::Visitor for HeadersVisitor { + type Value = SerializableHeaders; + + fn visit_map(&mut self, mut visitor: V) -> Result + where V: de::MapVisitor { + let mut result = Headers::new(); + while let Some((key, value)) = try!(visitor.visit()) { + let (key, value): (String, String) = (key, value); + result.set_raw(key, vec![value.into_bytes()]); + } + try!(visitor.end()); + Ok(SerializableHeaders(result)) + } + } + + let result = SerializableHeaders(Headers::new()); + try!(deserializer.visit_map(HeadersVisitor)); + Ok(result) + } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct SerializableUrl(pub Url); + +impl Deref for SerializableUrl { + type Target = Url; + + fn deref(&self) -> &Url { + &self.0 + } +} + +impl DerefMut for SerializableUrl { + fn deref_mut(&mut self) -> &mut Url { + &mut self.0 + } +} + +impl Serialize for SerializableUrl { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + format!("{}", self.0).serialize(serializer) + } +} + +impl Deserialize for SerializableUrl { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let string_representation: String = try!(Deserialize::deserialize(deserializer)); + Ok(SerializableUrl(FromStr::from_str(&string_representation[..]).unwrap())) + } +} + +#[derive(Clone, PartialEq)] +pub struct SerializableContentType(pub ContentType); + +impl Deref for SerializableContentType { + type Target = ContentType; + + fn deref(&self) -> &ContentType { + &self.0 + } +} + +impl Serialize for SerializableContentType { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + format!("{}", self.0).serialize(serializer) + } +} + +impl Deserialize for SerializableContentType { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let string_representation: String = try!(Deserialize::deserialize(deserializer)); + Ok(SerializableContentType(Header::parse_header( + &[string_representation.into_bytes()]).unwrap())) + } +} + +#[derive(Clone, PartialEq)] +pub struct SerializableRawStatus(pub RawStatus); + +impl Deref for SerializableRawStatus { + type Target = RawStatus; + + fn deref(&self) -> &RawStatus { + &self.0 + } +} + +impl Serialize for SerializableRawStatus { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + ((self.0).0, (self.0).1.clone().into_owned()).serialize(serializer) + } +} + +impl Deserialize for SerializableRawStatus { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let representation: (u16, String) = try!(Deserialize::deserialize(deserializer)); + Ok(SerializableRawStatus(RawStatus(representation.0, Cow::Owned(representation.1)))) + } +} + +#[derive(Clone, PartialEq, Debug)] +pub struct SerializableStringResult(pub Result<(),String>); + +#[derive(Deserialize, Serialize)] +enum SerializableStringResultInternal { + Ok(()), + Err(String), +} + +impl Deref for SerializableStringResult { + type Target = Result<(),String>; + + fn deref(&self) -> &Result<(),String> { + &self.0 + } +} + +impl Serialize for SerializableStringResult { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + let result = match **self { + Ok(ref value) => SerializableStringResultInternal::Ok(*value), + Err(ref value) => SerializableStringResultInternal::Err((*value).clone()), + }; + result.serialize(serializer) + } +} + +impl Deserialize for SerializableStringResult { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let result: SerializableStringResultInternal = + try!(Deserialize::deserialize(deserializer)); + match result { + SerializableStringResultInternal::Ok(value) => Ok(SerializableStringResult(Ok(value))), + SerializableStringResultInternal::Err(value) => { + Ok(SerializableStringResult(Err(value))) + } + } + } +} diff --git a/components/script/cors.rs b/components/script/cors.rs index c5a99fac63d..1e274a5b9fd 100644 --- a/components/script/cors.rs +++ b/components/script/cors.rs @@ -12,6 +12,7 @@ use network_listener::{NetworkListener, PreInvoke}; use script_task::ScriptChan; use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction, Metadata}; +use net_traits::{SerializableStringResult}; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -144,7 +145,8 @@ impl CORSRequest { let mut context = listener.context.lock(); let context = context.as_mut().unwrap(); *context.response.borrow_mut() = Some(response); - listener.invoke_with_listener(ResponseAction::ResponseComplete(Ok(()))); + listener.invoke_with_listener(ResponseAction::ResponseComplete( + SerializableStringResult(Ok(())))); }); } diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 63a5a82a46c..02f75d3832b 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -181,8 +181,8 @@ impl DedicatedWorkerGlobalScope { let serialized_url = url.serialize(); let parent_sender_for_reporter = parent_sender.clone(); let global = DedicatedWorkerGlobalScope::new( - url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), resource_task, - constellation_chan, parent_sender, own_sender, receiver); + url.0, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), + resource_task, constellation_chan, parent_sender, own_sender, receiver); // FIXME(njn): workers currently don't have a unique ID suitable for using in reporter // registration (#6631), so we instead use a random number and cross our fingers. let reporter_name = format!("worker-reporter-{}", random::()); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 9df842dddfc..2e5a479f4e6 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -74,7 +74,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyMod use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL}; use net_traits::CookieSource::NonHTTP; use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; -use net_traits::{Metadata, PendingAsyncLoad, AsyncResponseTarget}; +use net_traits::{Metadata, PendingAsyncLoad, AsyncResponseTarget, SerializableUrl}; use script_task::Runnable; use script_traits::{MouseButton, UntrustedNodeAddress}; use util::opts; @@ -1721,7 +1721,9 @@ impl<'a> DocumentMethods for &'a Document { } let window = self.window.root(); let (tx, rx) = channel(); - let _ = window.r().resource_task().send(GetCookiesForUrl(url, tx, NonHTTP)); + let _ = window.r().resource_task().send(GetCookiesForUrl(SerializableUrl(url), + tx, + NonHTTP)); let cookies = rx.recv().unwrap(); Ok(cookies.unwrap_or("".to_owned())) } @@ -1734,7 +1736,9 @@ impl<'a> DocumentMethods for &'a Document { return Err(Security); } let window = self.window.root(); - let _ = window.r().resource_task().send(SetCookiesForUrl(url, cookie, NonHTTP)); + let _ = window.r().resource_task().send(SetCookiesForUrl(SerializableUrl(url), + cookie, + NonHTTP)); Ok(()) } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 3329e0f0af9..56ea651ef7d 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -392,7 +392,7 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement { // encoding as the fallback encoding. (UTF_8.decode(&*bytes, DecoderTrap::Replace).unwrap(), true, - metadata.final_url) + metadata.final_url.0) }, // Step 2.b.1.c. diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index a81fe125973..6e12320b682 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -84,7 +84,7 @@ impl ParserContext { impl AsyncResponseListener for ParserContext { fn headers_available(&self, metadata: Metadata) { - let content_type = metadata.content_type.clone(); + let content_type = metadata.content_type.clone().map(|content_type| content_type.0); let parser = ScriptTask::page_fetch_complete(self.id.clone(), self.subpage.clone(), metadata); diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 9ec68cb0fd2..7cb33d1b023 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -46,7 +46,8 @@ use js::jsval::{JSVal, NullValue, UndefinedValue}; use net_traits::ControlMsg::Load; use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadConsumer}; -use net_traits::{AsyncResponseListener, Metadata}; +use net_traits::{AsyncResponseListener, Metadata, SerializableHeaders, SerializableMethod}; +use net_traits::{SerializableUrl}; use cors::{allow_cross_origin_request, CORSRequest, RequestMode, AsyncCORSResponseListener}; use cors::CORSResponse; use util::str::DOMString; @@ -216,7 +217,7 @@ impl XMLHttpRequest { let mut load_data = self.load_data.borrow_mut().take().unwrap(); load_data.cors = Some(ResourceCORSData { preflight: self.req.preflight_flag, - origin: self.req.origin.clone() + origin: SerializableUrl(self.req.origin.clone()) }); XMLHttpRequest::initiate_async_xhr(self.xhr.clone(), self.script_chan.clone(), @@ -539,14 +540,15 @@ impl<'a> XMLHttpRequestMethods for &'a XMLHttpRequest { None => () } - load_data.preserved_headers = (*self.request_headers.borrow()).clone(); + load_data.preserved_headers = + SerializableHeaders((*self.request_headers.borrow()).clone()); if !load_data.preserved_headers.has::() { let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]); load_data.preserved_headers.set(Accept(vec![qitem(mime)])); } - load_data.method = (*self.request_method.borrow()).clone(); + load_data.method = SerializableMethod((*self.request_method.borrow()).clone()); // CORS stuff let global = self.global.root(); @@ -556,10 +558,13 @@ impl<'a> XMLHttpRequestMethods for &'a XMLHttpRequest { } else { RequestMode::CORS }; - let mut combined_headers = load_data.headers.clone(); + let mut combined_headers = (*load_data.headers).clone(); combined_headers.extend(load_data.preserved_headers.iter()); - let cors_request = CORSRequest::maybe_new(referer_url.clone(), load_data.url.clone(), mode, - load_data.method.clone(), combined_headers); + let cors_request = CORSRequest::maybe_new(referer_url.clone(), + (*load_data.url).clone(), + mode, + (*load_data.method).clone(), + combined_headers); match cors_request { Ok(None) => { let mut buf = String::new(); @@ -780,8 +785,10 @@ impl<'a> PrivateXMLHttpRequestHelpers for &'a XMLHttpRequest { _ => {} }; // XXXManishearth Clear cache entries in case of a network error - self.process_partial_response(XHRProgress::HeadersReceived(gen_id, - metadata.headers, metadata.status)); + self.process_partial_response(XHRProgress::HeadersReceived( + gen_id, + metadata.headers.map(|headers| headers.0), + metadata.status.map(|status| status.0))); Ok(()) } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 7deed84430d..192c922991a 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -67,8 +67,10 @@ use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, W use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::webdriver_msg::WebDriverScriptCommand; -use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata}; use net_traits::LoadData as NetLoadData; +use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata}; +use net_traits::{SerializableContentType, SerializableHeaders, SerializableMethod}; +use net_traits::{SerializableUrl}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult}; use net_traits::storage_task::StorageTask; use profile_traits::mem::{self, Report, Reporter, ReporterRequest, ReportKind, ReportsChan}; @@ -1309,7 +1311,7 @@ impl ScriptTask { /// The entry point to document loading. Defines bindings, sets up the window and document /// objects, parses HTML and CSS, and kicks off initial layout. fn load(&self, metadata: Metadata, incomplete: InProgressLoad) -> Root { - let final_url = metadata.final_url.clone(); + let final_url = (*metadata.final_url).clone(); debug!("ScriptTask: loading {} on page {:?}", incomplete.url.serialize(), incomplete.pipeline_id); // We should either be initializing a root page or loading a child page of an @@ -1415,7 +1417,11 @@ impl ScriptTask { }); let content_type = match metadata.content_type { - Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => Some("text/plain".to_owned()), + Some(SerializableContentType(ContentType(Mime(TopLevel::Text, + SubLevel::Plain, + _)))) => { + Some("text/plain".to_owned()) + } _ => None }; @@ -1690,10 +1696,10 @@ impl ScriptTask { } resource_task.send(ControlMsg::Load(NetLoadData { - url: load_data.url, - method: load_data.method, - headers: Headers::new(), - preserved_headers: load_data.headers, + url: SerializableUrl(load_data.url), + method: SerializableMethod(load_data.method), + headers: SerializableHeaders(Headers::new()), + preserved_headers: SerializableHeaders(load_data.headers), data: load_data.data, cors: None, pipeline_id: Some(id), From 44d13f7fd419bdff1420ed21ca3efd72f4015bfa Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 9 Jul 2015 16:50:06 -0700 Subject: [PATCH 2/5] net: Use a thread for each `AsyncResponseTarget` to avoid having to send trait objects across process boundaries. --- components/net/image_cache_task.rs | 24 +++++++++++++++------- components/net/resource_task.rs | 2 +- components/net_traits/lib.rs | 14 +++++++++---- components/script/cors.rs | 8 +++++++- components/script/document_loader.rs | 2 +- components/script/dom/document.rs | 4 ++-- components/script/dom/htmlscriptelement.rs | 12 +++++++++-- components/script/dom/xmlhttprequest.rs | 14 +++++++++---- components/script/network_listener.rs | 18 +++++++++------- components/script/script_task.rs | 11 ++++++++-- 10 files changed, 78 insertions(+), 31 deletions(-) diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs index 865e8c6e37b..827aa4a24aa 100644 --- a/components/net/image_cache_task.rs +++ b/components/net/image_cache_task.rs @@ -14,6 +14,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem; use std::sync::Arc; use std::sync::mpsc::{channel, Sender, Receiver, Select}; +use std::thread; use util::resource_files::resources_dir_path; use util::task::spawn_named; use util::taskpool::TaskPool; @@ -100,14 +101,17 @@ struct ResourceLoadInfo { struct ResourceListener { url: Url, sender: Sender, + receiver: Receiver, } -impl AsyncResponseTarget for ResourceListener { - fn invoke_with_listener(&self, action: ResponseAction) { - self.sender.send(ResourceLoadInfo { - action: action, - url: self.url.clone(), - }).unwrap(); +impl ResourceListener { + fn run(&self) { + while let Ok(action) = self.receiver.recv() { + self.sender.send(ResourceLoadInfo { + action: action, + url: self.url.clone(), + }).unwrap(); + } } } @@ -330,11 +334,17 @@ impl ImageCache { e.insert(pending_load); let load_data = LoadData::new(url.clone(), None); + let (action_sender, action_receiver) = channel(); let listener = box ResourceListener { url: url, sender: self.progress_sender.clone(), + receiver: action_receiver, }; - let msg = ControlMsg::Load(load_data, LoadConsumer::Listener(listener)); + let msg = ControlMsg::Load(load_data, + LoadConsumer::Listener(AsyncResponseTarget { + sender: action_sender, + })); + thread::spawn(move || listener.run()); self.resource_task.send(msg).unwrap(); } } diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index d206e252c93..dfc2f2fe7e4 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -69,7 +69,7 @@ pub fn global_init() { pub enum ProgressSender { Channel(Sender), - Listener(Box), + Listener(AsyncResponseTarget), } impl ProgressSender { diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 8e243195cf6..4eac0e2efda 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -114,14 +114,20 @@ impl ResponseAction { /// A target for async networking events. Commonly used to dispatch a runnable event to another /// thread storing the wrapped closure for later execution. -pub trait AsyncResponseTarget { - fn invoke_with_listener(&self, action: ResponseAction); +pub struct AsyncResponseTarget { + pub sender: Sender, +} + +impl AsyncResponseTarget { + pub fn invoke_with_listener(&self, action: ResponseAction) { + self.sender.send(action).unwrap() + } } /// A wrapper for a network load that can either be channel or event-based. pub enum LoadConsumer { Channel(Sender), - Listener(Box), + Listener(AsyncResponseTarget), } /// Handle to a resource task @@ -195,7 +201,7 @@ impl PendingAsyncLoad { } /// Initiate the network request associated with this pending load, using the provided target. - pub fn load_async(mut self, listener: Box) { + pub fn load_async(mut self, listener: AsyncResponseTarget) { self.guard.neuter(); let load_data = LoadData::new(self.url, self.pipeline); let consumer = LoadConsumer::Listener(listener); diff --git a/components/script/cors.rs b/components/script/cors.rs index 1e274a5b9fd..e2ecb1da5cb 100644 --- a/components/script/cors.rs +++ b/components/script/cors.rs @@ -17,6 +17,7 @@ use net_traits::{SerializableStringResult}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::RefCell; +use std::sync::mpsc; use std::sync::{Arc, Mutex}; use time; use time::{now, Timespec}; @@ -132,9 +133,14 @@ impl CORSRequest { listener: listener, response: RefCell::new(None), }; + let (action_sender, action_receiver) = mpsc::channel(); let listener = NetworkListener { context: Arc::new(Mutex::new(context)), script_chan: script_chan, + receiver: action_receiver, + }; + let response_target = AsyncResponseTarget { + sender: action_sender, }; // TODO: this exists only to make preflight check non-blocking @@ -145,7 +151,7 @@ impl CORSRequest { let mut context = listener.context.lock(); let context = context.as_mut().unwrap(); *context.response.borrow_mut() = Some(response); - listener.invoke_with_listener(ResponseAction::ResponseComplete( + response_target.invoke_with_listener(ResponseAction::ResponseComplete( SerializableStringResult(Ok(())))); }); } diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index a59b4895b9e..439fc98367a 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -73,7 +73,7 @@ impl DocumentLoader { } /// Create and initiate a new network request. - pub fn load_async(&mut self, load: LoadType, listener: Box) { + pub fn load_async(&mut self, load: LoadType, listener: AsyncResponseTarget) { let pending = self.prepare_async_load(load); pending.load_async(listener) } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 2e5a479f4e6..31800bcc014 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -283,7 +283,7 @@ pub trait DocumentHelpers<'a> { /// https://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm fn invoke_animation_callbacks(self); fn prepare_async_load(self, load: LoadType) -> PendingAsyncLoad; - fn load_async(self, load: LoadType, listener: Box); + fn load_async(self, load: LoadType, listener: AsyncResponseTarget); fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec), String>; fn finish_load(self, load: LoadType); fn set_current_parser(self, script: Option<&ServoHTMLParser>); @@ -968,7 +968,7 @@ impl<'a> DocumentHelpers<'a> for &'a Document { loader.prepare_async_load(load) } - fn load_async(self, load: LoadType, listener: Box) { + fn load_async(self, load: LoadType, listener: AsyncResponseTarget) { let mut loader = self.loader.borrow_mut(); loader.load_async(load, listener) } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 56ea651ef7d..8e28fa51b62 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -40,12 +40,14 @@ use js::jsval::UndefinedValue; use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{Encoding, EncodingRef, DecoderTrap}; -use net_traits::{Metadata, AsyncResponseListener}; +use net_traits::{Metadata, AsyncResponseListener, AsyncResponseTarget}; use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; use html5ever::tree_builder::NextParserState; use std::cell::{RefCell, Cell}; use std::mem; +use std::sync::mpsc; use std::sync::{Arc, Mutex}; +use std::thread; use string_cache::Atom; use url::{Url, UrlParser}; @@ -330,12 +332,18 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement { url: url.clone(), })); + let (action_sender, action_receiver) = mpsc::channel(); let listener = box NetworkListener { context: context, script_chan: script_chan, + receiver: action_receiver, }; + let response_target = AsyncResponseTarget { + sender: action_sender, + }; + thread::spawn(move || listener.run()); - doc.r().load_async(LoadType::Script(url), listener); + doc.r().load_async(LoadType::Script(url), response_target); if self.parser_inserted.get() { doc.r().get_current_parser().unwrap().r().suspend(); diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 7cb33d1b023..ed4bfe1a705 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -46,8 +46,8 @@ use js::jsval::{JSVal, NullValue, UndefinedValue}; use net_traits::ControlMsg::Load; use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadConsumer}; -use net_traits::{AsyncResponseListener, Metadata, SerializableHeaders, SerializableMethod}; -use net_traits::{SerializableUrl}; +use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, SerializableHeaders}; +use net_traits::{SerializableMethod, SerializableUrl}; use cors::{allow_cross_origin_request, CORSRequest, RequestMode, AsyncCORSResponseListener}; use cors::CORSResponse; use util::str::DOMString; @@ -59,7 +59,7 @@ use std::cell::{RefCell, Cell}; use std::default::Default; use std::sync::{Mutex, Arc}; use std::sync::mpsc::{channel, Sender, TryRecvError}; -use std::thread::sleep_ms; +use std::thread::{self, sleep_ms}; use time; use url::{Url, UrlParser}; @@ -271,11 +271,17 @@ impl XMLHttpRequest { } } + let (action_sender, action_receiver) = channel(); let listener = box NetworkListener { context: context, script_chan: script_chan, + receiver: action_receiver, }; - resource_task.send(Load(load_data, LoadConsumer::Listener(listener))).unwrap(); + let response_target = AsyncResponseTarget { + sender: action_sender, + }; + thread::spawn(move || listener.run()); + resource_task.send(Load(load_data, LoadConsumer::Listener(response_target))).unwrap(); } } diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index 5f400eb76b3..2abff122309 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -3,7 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use script_task::{ScriptChan, ScriptMsg, Runnable}; -use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction}; +use net_traits::{AsyncResponseListener, ResponseAction}; +use std::sync::mpsc::Receiver; use std::sync::{Arc, Mutex}; /// An off-thread sink for async network event runnables. All such events are forwarded to @@ -11,14 +12,17 @@ use std::sync::{Arc, Mutex}; pub struct NetworkListener { pub context: Arc>, pub script_chan: Box, + pub receiver: Receiver, } -impl AsyncResponseTarget for NetworkListener { - fn invoke_with_listener(&self, action: ResponseAction) { - self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { - context: self.context.clone(), - action: action, - })).unwrap(); +impl NetworkListener { + pub fn run(&self) { + while let Ok(action) = self.receiver.recv() { + self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { + context: self.context.clone(), + action: action, + })).unwrap(); + } } } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 192c922991a..fab0908683c 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -68,7 +68,7 @@ use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; -use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata}; +use net_traits::{AsyncResponseTarget, ResourceTask, LoadConsumer, ControlMsg, Metadata}; use net_traits::{SerializableContentType, SerializableHeaders, SerializableMethod}; use net_traits::{SerializableUrl}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult}; @@ -105,6 +105,7 @@ use std::rc::Rc; use std::result::Result; use std::sync::{Arc, Mutex}; use std::sync::mpsc::{channel, Sender, Receiver, Select}; +use std::thread; use time::Tm; use hyper::header::{ContentType, HttpDate}; @@ -1686,9 +1687,15 @@ impl ScriptTask { let context = Arc::new(Mutex::new(ParserContext::new(id, subpage, script_chan.clone(), load_data.url.clone()))); + let (action_sender, action_receiver) = channel(); let listener = box NetworkListener { context: context, script_chan: script_chan.clone(), + receiver: action_receiver, + }; + thread::spawn(move || listener.run()); + let response_target = AsyncResponseTarget { + sender: action_sender, }; if load_data.url.scheme == "javascript" { @@ -1703,7 +1710,7 @@ impl ScriptTask { data: load_data.data, cors: None, pipeline_id: Some(id), - }, LoadConsumer::Listener(listener))).unwrap(); + }, LoadConsumer::Listener(response_target))).unwrap(); self.incomplete_loads.borrow_mut().push(incomplete); } From 2aa51742460a351abfb746aec4352dd6d27a3c52 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 9 Jul 2015 17:16:21 -0700 Subject: [PATCH 3/5] script: Make the resource task communication use IPC channels. --- components/compositing/Cargo.toml | 6 +- components/gfx/Cargo.toml | 5 +- components/layout/Cargo.toml | 5 +- components/layout/layout_task.rs | 2 +- components/layout_traits/Cargo.toml | 5 +- components/net/Cargo.toml | 6 +- components/net/about_loader.rs | 17 +- components/net/data_loader.rs | 17 +- components/net/file_loader.rs | 12 +- components/net/http_loader.rs | 49 ++- components/net/image_cache_task.rs | 43 +-- components/net/resource_task.rs | 35 +- components/net_traits/Cargo.toml | 4 + components/net_traits/lib.rs | 315 +++--------------- components/profile_traits/Cargo.toml | 5 +- components/script/Cargo.toml | 2 +- components/script/cors.rs | 12 +- components/script/dom/bindings/trace.rs | 8 +- .../script/dom/dedicatedworkerglobalscope.rs | 2 +- components/script/dom/document.rs | 13 +- components/script/dom/htmlscriptelement.rs | 13 +- components/script/dom/servohtmlparser.rs | 2 +- components/script/dom/xmlhttprequest.rs | 34 +- components/script/network_listener.rs | 14 +- components/script/script_task.rs | 24 +- components/script_traits/Cargo.toml | 5 +- components/servo/Cargo.lock | 1 + components/servo/Cargo.toml | 5 +- components/style/Cargo.toml | 5 +- components/util/Cargo.toml | 5 +- components/webdriver_server/Cargo.toml | 5 +- tests/unit/net/Cargo.toml | 3 + tests/unit/net/data_loader.rs | 3 +- tests/unit/net/lib.rs | 1 + tests/unit/net/resource_task.rs | 9 +- 35 files changed, 234 insertions(+), 458 deletions(-) diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 6d75015d7b3..e3ec5f2ed24 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -66,10 +66,13 @@ git = "https://github.com/pcwalton/ipc-channel" git = "https://github.com/ecoal95/rust-offscreen-rendering-context" features = ["texture_surface"] +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" num = "0.1.24" -url = "0.2.36" time = "0.1.17" libc = "0.1" gleam = "0.1" @@ -80,3 +83,4 @@ core-graphics = "0.1" [target.x86_64-apple-darwin.dependencies.core-text] git = "https://github.com/servo/core-text-rs" + diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index 1e7894b86b0..9ec80d3e091 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -47,10 +47,13 @@ path = "../script_traits" [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" fnv = "1.0" -url = "0.2.36" time = "0.1.12" bitflags = "0.3" rustc-serialize = "0.3" diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 314b3da4b72..d1ed4e112ad 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -62,11 +62,14 @@ features = [ "serde-serialization" ] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" encoding = "0.2" fnv = "1.0" -url = "0.2.36" bitflags = "0.3" rustc-serialize = "0.3" libc = "0.1" diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 12a2b549c38..001f8f42d2a 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -718,7 +718,7 @@ impl LayoutTask { // TODO we don't really even need to load this if mq does not match let (metadata, iter) = load_bytes_iter(pending); let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url.0; + let final_url = metadata.final_url; let sheet = Stylesheet::from_bytes_iter(iter, final_url, diff --git a/components/layout_traits/Cargo.toml b/components/layout_traits/Cargo.toml index f92fc5bb657..355a5ddc265 100644 --- a/components/layout_traits/Cargo.toml +++ b/components/layout_traits/Cargo.toml @@ -28,8 +28,11 @@ path = "../util" [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] -url = "0.2.36" euclid = "0.1" serde = "0.4" serde_macros = "0.4" diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index a76178f0085..3d304658b1e 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -27,9 +27,12 @@ features = [ "serde-serialization" ] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" -url = "0.2.36" time = "0.1.17" openssl="0.6.1" rustc-serialize = "0.3" @@ -39,3 +42,4 @@ regex_macros = "0.1.8" flate2 = "0.2.0" uuid = "0.1.16" euclid = "0.1" + diff --git a/components/net/about_loader.rs b/components/net/about_loader.rs index d20a3e4ef63..aab22f1a2f9 100644 --- a/components/net/about_loader.rs +++ b/components/net/about_loader.rs @@ -2,8 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer, SerializableContentType, SerializableRawStatus}; -use net_traits::{SerializableStringResult, SerializableUrl}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::Done; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -23,14 +22,12 @@ pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Ar "blank" => { let chan = start_sending(start_chan, Metadata { final_url: load_data.url, - content_type: Some(SerializableContentType(ContentType(Mime(TopLevel::Text, - SubLevel::Html, - vec![])))), + content_type: Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))), charset: Some("utf-8".to_string()), headers: None, - status: Some(SerializableRawStatus(RawStatus(200, "OK".into()))), + status: Some(RawStatus(200, "OK".into())), }); - chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); + chan.send(Done(Ok(()))).unwrap(); return } "crash" => panic!("Loading the about:crash URL."), @@ -38,11 +35,11 @@ pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Ar let mut path = resources_dir_path(); path.push("failure.html"); assert!(path.exists()); - load_data.url = SerializableUrl(Url::from_file_path(&*path).unwrap()); + load_data.url = Url::from_file_path(&*path).unwrap(); } _ => { - start_sending(start_chan, Metadata::default(load_data.url.0)) - .send(Done(SerializableStringResult(Err("Unknown about: URL.".to_string())))) + start_sending(start_chan, Metadata::default(load_data.url)) + .send(Done(Err("Unknown about: URL.".to_string()))) .unwrap(); return } diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs index f1f99d6efe2..d4bad86a412 100644 --- a/components/net/data_loader.rs +++ b/components/net/data_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer, SerializableStringResult}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -26,11 +26,11 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) { let url = load_data.url; assert!(&*url.scheme == "data"); - let mut metadata = Metadata::default((*url).clone()); + let mut metadata = Metadata::default(url.clone()); // Split out content type and data. let mut scheme_data = match url.scheme_data { - SchemeData::NonRelative(ref scheme_data) => (*scheme_data).clone(), + SchemeData::NonRelative(scheme_data) => scheme_data, _ => panic!("Expected a non-relative scheme URL.") }; match url.query { @@ -42,8 +42,8 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) { } let parts: Vec<&str> = scheme_data.splitn(2, ',').collect(); if parts.len() != 2 { - start_sending(start_chan, metadata).send(Done(SerializableStringResult(Err( - "invalid data uri".to_string())))).unwrap(); + start_sending(start_chan, + metadata).send(Done(Err("invalid data uri".to_string()))).unwrap(); return; } @@ -70,16 +70,15 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) { let bytes = bytes.into_iter().filter(|&b| b != ' ' as u8).collect::>(); match bytes.from_base64() { Err(..) => { - progress_chan.send(Done(SerializableStringResult(Err( - "non-base64 data uri".to_string())))).unwrap(); + progress_chan.send(Done(Err("non-base64 data uri".to_string()))).unwrap(); } Ok(data) => { progress_chan.send(Payload(data)).unwrap(); - progress_chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); + progress_chan.send(Done(Ok(()))).unwrap(); } } } else { progress_chan.send(Payload(bytes)).unwrap(); - progress_chan.send(Done(SerializableStringResult(Ok(())))).unwrap(); + progress_chan.send(Done(Ok(()))).unwrap(); } } diff --git a/components/net/file_loader.rs b/components/net/file_loader.rs index 08de3298cf3..a81d0e8afdb 100644 --- a/components/net/file_loader.rs +++ b/components/net/file_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata, LoadConsumer, SerializableStringResult}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::{start_sending, start_sending_sniffed, ProgressSender}; @@ -48,7 +48,7 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc = url.to_file_path(); match file_path { Ok(file_path) => { @@ -65,19 +65,17 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc (res.map(|_| ()), start_sending(senders, metadata)), }; - progress_chan.send(Done(SerializableStringResult(res))).unwrap(); + progress_chan.send(Done(res)).unwrap(); } Err(e) => { let progress_chan = start_sending(senders, metadata); - progress_chan.send(Done(SerializableStringResult(Err(e.description() - .to_string())))) - .unwrap(); + progress_chan.send(Done(Err(e.description().to_string()))).unwrap(); } } } Err(_) => { let progress_chan = start_sending(senders, metadata); - progress_chan.send(Done(SerializableStringResult(Err(url.to_string())))).unwrap(); + progress_chan.send(Done(Err(url.to_string()))).unwrap(); } } }); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index cc186787985..d5e75bc2e1b 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -2,15 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, SerializableMethod}; -use net_traits::{SerializableHeaders, SerializableRawStatus, SerializableStringResult}; -use net_traits::{SerializableUrl}; +use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent}; use mime_classifier::MIMEClassifier; use resource_task::{start_sending_opt, start_sending_sniffed_opt}; use hsts::{HSTSList, secure_url}; +use ipc_channel::ipc::{self, IpcSender}; use log; use std::collections::HashSet; use file_loader; @@ -38,7 +37,7 @@ use uuid; use std::borrow::ToOwned; use std::boxed::FnBox; -pub fn factory(cookies_chan: Sender, +pub fn factory(cookies_chan: IpcSender, devtools_chan: Option>, hsts_list: Arc>) -> Box) + Send> { @@ -53,7 +52,7 @@ fn send_error(url: Url, err: String, start_chan: LoadConsumer) { metadata.status = None; match start_sending_opt(start_chan, metadata) { - Ok(p) => p.send(Done(SerializableStringResult(Err(err)))).unwrap(), + Ok(p) => p.send(Done(Err(err))).unwrap(), _ => {} }; } @@ -88,7 +87,7 @@ fn request_must_be_secured(hsts_list: &HSTSList, url: &Url) -> bool { fn load(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Arc, - cookies_chan: Sender, + cookies_chan: IpcSender, devtools_chan: Option>, hsts_list: Arc>) { // FIXME: At the time of writing this FIXME, servo didn't have any central @@ -96,7 +95,7 @@ fn load(mut load_data: LoadData, // repository DOES exist, please update this constant to use it. let max_redirects = 50; let mut iters = 0; - let mut url = load_data.url.0.clone(); + let mut url = load_data.url.clone(); let mut redirected_to = HashSet::new(); // If the URL is a view-source scheme then the scheme data contains the @@ -156,9 +155,7 @@ reason: \"certificate verify failed\" }]))"; &HttpsConnector::new(Openssl { context: Arc::new(context) })) }; - let mut req = match Request::with_connector(load_data.method.0.clone(), - url.clone(), - &mut connector) { + let mut req = match req { Ok(req) => req, Err(HttpError::Io(ref io_error)) if ( io_error.kind() == io::ErrorKind::Other && @@ -187,11 +184,11 @@ reason: \"certificate verify failed\" }]))"; // https://bugzilla.mozilla.org/show_bug.cgi?id=216828 . // Only preserve ones which have been explicitly marked as such. if iters == 1 { - let mut combined_headers = (*load_data.headers).clone(); + let mut combined_headers = load_data.headers.clone(); combined_headers.extend(load_data.preserved_headers.iter()); *req.headers_mut() = combined_headers; } else { - *req.headers_mut() = (*load_data.preserved_headers).clone(); + *req.headers_mut() = load_data.preserved_headers.clone(); } req.headers_mut().set(host); @@ -206,8 +203,8 @@ reason: \"certificate verify failed\" }]))"; req.headers_mut().set(accept); } - let (tx, rx) = channel(); - cookies_chan.send(ControlMsg::GetCookiesForUrl(SerializableUrl(url.clone()), + let (tx, rx) = ipc::channel().unwrap(); + cookies_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), tx, CookieSource::HTTP)).unwrap(); if let Some(cookie_list) = rx.recv().unwrap() { @@ -220,7 +217,7 @@ reason: \"certificate verify failed\" }]))"; req.headers_mut().set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]); } if log_enabled!(log::LogLevel::Info) { - info!("{}", load_data.method.0); + info!("{}", load_data.method); for header in req.headers().iter() { info!(" - {}", header); } @@ -248,7 +245,7 @@ reason: \"certificate verify failed\" }]))"; writer }, _ => { - match *load_data.method { + match load_data.method { Method::Get | Method::Head => (), _ => req.headers_mut().set(ContentLength(0)) } @@ -266,9 +263,9 @@ reason: \"certificate verify failed\" }]))"; // TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id in the message let request_id = uuid::Uuid::new_v4().to_simple_string(); if let Some(ref chan) = devtools_chan { - let net_event = NetworkEvent::HttpRequest((*load_data.url).clone(), - (*load_data.method).clone(), - (*load_data.headers).clone(), + let net_event = NetworkEvent::HttpRequest(load_data.url.clone(), + load_data.method.clone(), + load_data.headers.clone(), load_data.data.clone()); chan.send(DevtoolsControlMsg::FromChrome( ChromeToDevtoolsControlMsg::NetworkEventMessage(request_id.clone(), @@ -294,7 +291,7 @@ reason: \"certificate verify failed\" }]))"; if let Some(cookies) = response.headers.get_raw("set-cookie") { for cookie in cookies.iter() { if let Ok(cookies) = String::from_utf8(cookie.clone()) { - cookies_chan.send(ControlMsg::SetCookiesForUrl(SerializableUrl(url.clone()), + cookies_chan.send(ControlMsg::SetCookiesForUrl(url.clone(), cookies, CookieSource::HTTP)).unwrap(); } @@ -332,10 +329,10 @@ reason: \"certificate verify failed\" }]))"; // According to https://tools.ietf.org/html/rfc7231#section-6.4.2, // historically UAs have rewritten POST->GET on 301 and 302 responses. - if *load_data.method == Method::Post && + if load_data.method == Method::Post && (response.status == StatusCode::MovedPermanently || response.status == StatusCode::Found) { - load_data.method = SerializableMethod(Method::Get); + load_data.method = Method::Get; } if redirected_to.contains(&url) { @@ -359,8 +356,8 @@ reason: \"certificate verify failed\" }]))"; Some(&ContentType(ref mime)) => Some(mime), None => None }); - metadata.headers = Some(SerializableHeaders(adjusted_headers)); - metadata.status = Some(SerializableRawStatus(response.status_raw().clone())); + metadata.headers = Some(adjusted_headers); + metadata.status = Some(response.status_raw().clone()); let mut encoding_str: Option = None; //FIXME: Implement Content-Encoding Header https://github.com/hyperium/hyper/issues/391 @@ -396,7 +393,7 @@ reason: \"certificate verify failed\" }]))"; send_data(&mut response_decoding, start_chan, metadata, classifier); } Err(err) => { - send_error((*metadata.final_url).clone(), err.to_string(), start_chan); + send_error(metadata.final_url, err.to_string(), start_chan); return; } } @@ -445,5 +442,5 @@ fn send_data(reader: &mut R, }; } - let _ = progress_chan.send(Done(SerializableStringResult(Ok(())))); + let _ = progress_chan.send(Done(Ok(()))); } diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs index 827aa4a24aa..7c672b1e604 100644 --- a/components/net/image_cache_task.rs +++ b/components/net/image_cache_task.rs @@ -14,7 +14,6 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem; use std::sync::Arc; use std::sync::mpsc::{channel, Sender, Receiver, Select}; -use std::thread; use util::resource_files::resources_dir_path; use util::task::spawn_named; use util::taskpool::TaskPool; @@ -98,23 +97,6 @@ struct ResourceLoadInfo { url: Url, } -struct ResourceListener { - url: Url, - sender: Sender, - receiver: Receiver, -} - -impl ResourceListener { - fn run(&self) { - while let Ok(action) = self.receiver.recv() { - self.sender.send(ResourceLoadInfo { - action: action, - url: self.url.clone(), - }).unwrap(); - } - } -} - /// Implementation of the image cache struct ImageCache { // Receive commands from clients @@ -252,10 +234,10 @@ impl ImageCache { pending_load.bytes.push_all(&data); } ResponseAction::ResponseComplete(result) => { - match *result { + match result { Ok(()) => { let pending_load = self.pending_loads.get_mut(&msg.url).unwrap(); - pending_load.result = Some((*result).clone()); + pending_load.result = Some(result); let bytes = mem::replace(&mut pending_load.bytes, vec!()); let url = msg.url.clone(); @@ -334,17 +316,20 @@ impl ImageCache { e.insert(pending_load); let load_data = LoadData::new(url.clone(), None); - let (action_sender, action_receiver) = channel(); - let listener = box ResourceListener { - url: url, - sender: self.progress_sender.clone(), - receiver: action_receiver, + let (action_sender, action_receiver) = ipc::channel().unwrap(); + let response_target = AsyncResponseTarget { + sender: action_sender, }; let msg = ControlMsg::Load(load_data, - LoadConsumer::Listener(AsyncResponseTarget { - sender: action_sender, - })); - thread::spawn(move || listener.run()); + LoadConsumer::Listener(response_target)); + let progress_sender = self.progress_sender.clone(); + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + let action: ResponseAction = message.to().unwrap(); + progress_sender.send(ResourceLoadInfo { + action: action, + url: url.clone(), + }).unwrap(); + }); self.resource_task.send(msg).unwrap(); } } diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index dfc2f2fe7e4..70c0ec71a4b 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -12,9 +12,8 @@ use cookie_storage::CookieStorage; use cookie; use mime_classifier::MIMEClassifier; -use net_traits::{ControlMsg, LoadData, LoadResponse, LoadConsumer}; +use net_traits::{ControlMsg, LoadData, LoadResponse, LoadConsumer, CookieSource}; use net_traits::{Metadata, ProgressMsg, ResourceTask, AsyncResponseTarget, ResponseAction}; -use net_traits::{CookieSource, SerializableContentType, SerializableStringResult}; use net_traits::ProgressMsg::Done; use util::opts; use util::task::spawn_named; @@ -25,6 +24,7 @@ use hsts::{HSTSList, HSTSEntry, preload_hsts_domains}; use devtools_traits::{DevtoolsControlMsg}; use hyper::header::{ContentType, Header, SetCookie, UserAgent}; use hyper::mime::{Mime, TopLevel, SubLevel}; +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use regex::Regex; use std::borrow::ToOwned; @@ -35,7 +35,7 @@ use std::fs::File; use std::io::{BufReader, Read}; use std::sync::Arc; use std::sync::Mutex; -use std::sync::mpsc::{channel, Receiver, Sender}; +use std::sync::mpsc::{channel, Sender}; static mut HOST_TABLE: Option<*mut HashMap> = None; pub static IPV4_REGEX: Regex = regex!( @@ -68,7 +68,7 @@ pub fn global_init() { } pub enum ProgressSender { - Channel(Sender), + Channel(IpcSender), Listener(AsyncResponseTarget), } @@ -126,16 +126,14 @@ pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadat } let supplied_type = - metadata.content_type.map(|SerializableContentType(ContentType(Mime(toplevel, - sublevel, - _)))| { + metadata.content_type.map(|ContentType(Mime(toplevel, sublevel, _))| { (format!("{}", toplevel), format!("{}", sublevel)) }); metadata.content_type = classifier.classify(nosniff, check_for_apache_bug, &supplied_type, &partial_body).map(|(toplevel, sublevel)| { let mime_tp: TopLevel = toplevel.parse().unwrap(); let mime_sb: SubLevel = sublevel.parse().unwrap(); - SerializableContentType(ContentType(Mime(mime_tp, mime_sb, vec!()))) + ContentType(Mime(mime_tp, mime_sb, vec!())) }); } @@ -147,7 +145,7 @@ pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadat pub fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata) -> Result { match start_chan { LoadConsumer::Channel(start_chan) => { - let (progress_chan, progress_port) = channel(); + let (progress_chan, progress_port) = ipc::channel().unwrap(); let result = start_chan.send(LoadResponse { metadata: metadata, progress_port: progress_port, @@ -172,7 +170,7 @@ pub fn new_resource_task(user_agent: Option, None => HSTSList::new() }; - let (setup_chan, setup_port) = channel(); + let (setup_chan, setup_port) = ipc::channel().unwrap(); let setup_chan_clone = setup_chan.clone(); spawn_named("ResourceManager".to_owned(), move || { let resource_manager = ResourceManager::new( @@ -222,7 +220,7 @@ pub fn replace_hosts(mut load_data: LoadData, host_table: *mut HashMap, + from_client: IpcReceiver, resource_manager: ResourceManager } @@ -252,19 +250,18 @@ impl ResourceChannelManager { } } -pub struct ResourceManager { +struct ResourceManager { user_agent: Option, cookie_storage: CookieStorage, - // TODO: Can this be de-coupled? - resource_task: Sender, + resource_task: IpcSender, mime_classifier: Arc, devtools_chan: Option>, hsts_list: Arc> } impl ResourceManager { - pub fn new(user_agent: Option, - resource_task: Sender, + fn new(user_agent: Option, + resource_task: IpcSender, hsts_list: HSTSList, devtools_channel: Option>) -> ResourceManager { ResourceManager { @@ -278,7 +275,6 @@ impl ResourceManager { } } - impl ResourceManager { fn set_cookies_for_url(&mut self, request: Url, cookie_list: String, source: CookieSource) { let header = Header::parse_header(&[cookie_list.into_bytes()]); @@ -325,9 +321,8 @@ impl ResourceManager { "about" => from_factory(about_loader::factory), _ => { debug!("resource_task: no loader for scheme {}", load_data.url.scheme); - start_sending(consumer, Metadata::default((*load_data.url).clone())) - .send(ProgressMsg::Done(SerializableStringResult(Err( - "no loader for scheme".to_string())))).unwrap(); + start_sending(consumer, Metadata::default(load_data.url)) + .send(ProgressMsg::Done(Err("no loader for scheme".to_string()))).unwrap(); return } }; diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index c3999b25fc9..fbed03472d3 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -31,6 +31,10 @@ features = [ "serde_serialization" ] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" euclid = "0.1" diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 4eac0e2efda..05837ec5054 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -22,20 +22,15 @@ extern crate url; extern crate util; extern crate msg; -use hyper::header::{ContentType, Header, Headers, HeadersItems}; +use hyper::header::{ContentType, Headers}; use hyper::http::RawStatus; use hyper::method::Method; use hyper::mime::{Mime, Attr}; +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use msg::constellation_msg::{PipelineId}; -use serde::de; -use serde::ser; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserializer, Serializer}; use url::Url; -use std::borrow::Cow; -use std::ops::{Deref, DerefMut}; -use std::str::FromStr; -use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; pub mod image_cache_task; @@ -52,12 +47,12 @@ pub mod image { #[derive(Clone, Deserialize, Serialize)] pub struct LoadData { - pub url: SerializableUrl, - pub method: SerializableMethod, + pub url: Url, + pub method: Method, /// Headers that will apply to the initial request only - pub headers: SerializableHeaders, + pub headers: Headers, /// Headers that will apply to the initial request and any redirects - pub preserved_headers: SerializableHeaders, + pub preserved_headers: Headers, pub data: Option>, pub cors: Option, pub pipeline_id: Option, @@ -66,10 +61,10 @@ pub struct LoadData { impl LoadData { pub fn new(url: Url, id: Option) -> LoadData { LoadData { - url: SerializableUrl(url), - method: SerializableMethod(Method::Get), - headers: SerializableHeaders(Headers::new()), - preserved_headers: SerializableHeaders(Headers::new()), + url: url, + method: Method::Get, + headers: Headers::new(), + preserved_headers: Headers::new(), data: None, cors: None, pipeline_id: id, @@ -98,7 +93,7 @@ pub enum ResponseAction { /// Invoke data_available DataAvailable(Vec), /// Invoke response_complete - ResponseComplete(SerializableStringResult) + ResponseComplete(Result<(), String>) } impl ResponseAction { @@ -107,15 +102,16 @@ impl ResponseAction { match self { ResponseAction::HeadersAvailable(m) => listener.headers_available(m), ResponseAction::DataAvailable(d) => listener.data_available(d), - ResponseAction::ResponseComplete(r) => listener.response_complete(r.0), + ResponseAction::ResponseComplete(r) => listener.response_complete(r), } } } /// A target for async networking events. Commonly used to dispatch a runnable event to another /// thread storing the wrapped closure for later execution. +#[derive(Deserialize, Serialize)] pub struct AsyncResponseTarget { - pub sender: Sender, + pub sender: IpcSender, } impl AsyncResponseTarget { @@ -125,27 +121,29 @@ impl AsyncResponseTarget { } /// A wrapper for a network load that can either be channel or event-based. +#[derive(Deserialize, Serialize)] pub enum LoadConsumer { - Channel(Sender), + Channel(IpcSender), Listener(AsyncResponseTarget), } /// Handle to a resource task -pub type ResourceTask = Sender; +pub type ResourceTask = IpcSender; -#[derive(PartialEq, Copy, Clone)] +#[derive(PartialEq, Copy, Clone, Deserialize, Serialize)] pub enum IncludeSubdomains { Included, NotIncluded } +#[derive(Deserialize, Serialize)] pub enum ControlMsg { /// Request the data associated with a particular URL Load(LoadData, LoadConsumer), /// Store a set of cookies for a given originating URL - SetCookiesForUrl(SerializableUrl, String, CookieSource), + SetCookiesForUrl(Url, String, CookieSource), /// Retrieve the stored cookies for a given URL - GetCookiesForUrl(SerializableUrl, Sender>, CookieSource), + GetCookiesForUrl(Url, IpcSender>, CookieSource), /// Store a domain's STS information SetHSTSEntryForHost(String, IncludeSubdomains, Option), Exit @@ -191,10 +189,10 @@ impl PendingAsyncLoad { } /// Initiate the network request associated with this pending load. - pub fn load(mut self) -> Receiver { + pub fn load(mut self) -> IpcReceiver { self.guard.neuter(); let load_data = LoadData::new(self.url, self.pipeline); - let (sender, receiver) = channel(); + let (sender, receiver) = ipc::channel().unwrap(); let consumer = LoadConsumer::Channel(sender); self.resource_task.send(ControlMsg::Load(load_data, consumer)).unwrap(); receiver @@ -214,11 +212,12 @@ impl PendingAsyncLoad { /// /// Even if loading fails immediately, we send one of these and the /// progress_port will provide the error. +#[derive(Serialize, Deserialize)] pub struct LoadResponse { /// Metadata, such as from HTTP headers. pub metadata: Metadata, /// Port for reading data. - pub progress_port: Receiver, + pub progress_port: IpcReceiver, } #[derive(Clone, Deserialize, Serialize)] @@ -226,38 +225,38 @@ pub struct ResourceCORSData { /// CORS Preflight flag pub preflight: bool, /// Origin of CORS Request - pub origin: SerializableUrl, + pub origin: Url, } /// Metadata about a loaded resource, such as is obtained from HTTP headers. #[derive(Clone, Deserialize, Serialize)] pub struct Metadata { /// Final URL after redirects. - pub final_url: SerializableUrl, + pub final_url: Url, /// MIME type / subtype. - pub content_type: Option<(SerializableContentType)>, + pub content_type: Option<(ContentType)>, /// Character set. pub charset: Option, /// Headers - pub headers: Option, + pub headers: Option, /// HTTP Status - pub status: Option, + pub status: Option, } impl Metadata { /// Metadata with defaults for everything optional. pub fn default(url: Url) -> Self { Metadata { - final_url: SerializableUrl(url), + final_url: url, content_type: None, charset: None, headers: None, // https://fetch.spec.whatwg.org/#concept-response-status-message - status: Some(SerializableRawStatus(RawStatus(200, "OK".into()))), + status: Some(RawStatus(200, "OK".into())), } } @@ -266,7 +265,7 @@ impl Metadata { match content_type { None => (), Some(mime) => { - self.content_type = Some(SerializableContentType(ContentType(mime.clone()))); + self.content_type = Some(ContentType(mime.clone())); let &Mime(_, _, ref parameters) = mime; for &(ref k, ref v) in parameters.iter() { if &Attr::Charset == k { @@ -293,24 +292,23 @@ pub enum ProgressMsg { /// Binary data - there may be multiple of these Payload(Vec), /// Indicates loading is complete, either successfully or not - Done(SerializableStringResult) + Done(Result<(), String>) } /// Convenience function for synchronously loading a whole resource. pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) -> Result<(Metadata, Vec), String> { - let (start_chan, start_port) = channel(); - resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(start_chan))).unwrap(); + let (start_chan, start_port) = ipc::channel().unwrap(); + resource_task.send(ControlMsg::Load(LoadData::new(url, None), + LoadConsumer::Channel(start_chan))).unwrap(); let response = start_port.recv().unwrap(); let mut buf = vec!(); loop { match response.progress_port.recv().unwrap() { ProgressMsg::Payload(data) => buf.push_all(&data), - ProgressMsg::Done(SerializableStringResult(Ok(()))) => { - return Ok((response.metadata, buf)) - } - ProgressMsg::Done(SerializableStringResult(Err(e))) => return Err(e) + ProgressMsg::Done(Ok(())) => return Ok((response.metadata, buf)), + ProgressMsg::Done(Err(e)) => return Err(e) } } } @@ -319,13 +317,15 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) pub fn load_bytes_iter(pending: PendingAsyncLoad) -> (Metadata, ProgressMsgPortIterator) { let input_port = pending.load(); let response = input_port.recv().unwrap(); - let iter = ProgressMsgPortIterator { progress_port: response.progress_port }; + let iter = ProgressMsgPortIterator { + progress_port: response.progress_port + }; (response.metadata, iter) } /// Iterator that reads chunks of bytes from a ProgressMsg port pub struct ProgressMsgPortIterator { - progress_port: Receiver + progress_port: IpcReceiver, } impl Iterator for ProgressMsgPortIterator { @@ -334,8 +334,8 @@ impl Iterator for ProgressMsgPortIterator { fn next(&mut self) -> Option> { match self.progress_port.recv().unwrap() { ProgressMsg::Payload(data) => Some(data), - ProgressMsg::Done(SerializableStringResult(Ok(()))) => None, - ProgressMsg::Done(SerializableStringResult(Err(e))) => { + ProgressMsg::Done(Ok(())) => None, + ProgressMsg::Done(Err(e)) => { error!("error receiving bytes: {}", e); None } @@ -343,226 +343,3 @@ impl Iterator for ProgressMsgPortIterator { } } -#[derive(Clone)] -pub struct SerializableMethod(pub Method); - -impl Deref for SerializableMethod { - type Target = Method; - - fn deref(&self) -> &Method { - &self.0 - } -} - -impl Serialize for SerializableMethod { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - format!("{}", self.0).serialize(serializer) - } -} - -impl Deserialize for SerializableMethod { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - let string_representation: String = try!(Deserialize::deserialize(deserializer)); - Ok(SerializableMethod(FromStr::from_str(&string_representation[..]).unwrap())) - } -} - -#[derive(Clone)] -pub struct SerializableHeaders(pub Headers); - -impl Deref for SerializableHeaders { - type Target = Headers; - - fn deref(&self) -> &Headers { - &self.0 - } -} - -impl DerefMut for SerializableHeaders { - fn deref_mut(&mut self) -> &mut Headers { - &mut self.0 - } -} - -impl Serialize for SerializableHeaders { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - struct HeadersVisitor<'a> { - iter: HeadersItems<'a>, - len: usize, - } - - impl<'a> ser::MapVisitor for HeadersVisitor<'a> { - fn visit(&mut self, serializer: &mut S) -> Result, S::Error> - where S: Serializer { - match self.iter.next() { - Some(header_item) => { - try!(serializer.visit_map_elt(header_item.name(), - header_item.value_string())); - Ok(Some(())) - } - None => Ok(None), - } - } - - fn len(&self) -> Option { - Some(self.len) - } - } - - serializer.visit_map(HeadersVisitor { - iter: self.iter(), - len: self.len(), - }) - } -} - -impl Deserialize for SerializableHeaders { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - struct HeadersVisitor; - - impl de::Visitor for HeadersVisitor { - type Value = SerializableHeaders; - - fn visit_map(&mut self, mut visitor: V) -> Result - where V: de::MapVisitor { - let mut result = Headers::new(); - while let Some((key, value)) = try!(visitor.visit()) { - let (key, value): (String, String) = (key, value); - result.set_raw(key, vec![value.into_bytes()]); - } - try!(visitor.end()); - Ok(SerializableHeaders(result)) - } - } - - let result = SerializableHeaders(Headers::new()); - try!(deserializer.visit_map(HeadersVisitor)); - Ok(result) - } -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct SerializableUrl(pub Url); - -impl Deref for SerializableUrl { - type Target = Url; - - fn deref(&self) -> &Url { - &self.0 - } -} - -impl DerefMut for SerializableUrl { - fn deref_mut(&mut self) -> &mut Url { - &mut self.0 - } -} - -impl Serialize for SerializableUrl { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - format!("{}", self.0).serialize(serializer) - } -} - -impl Deserialize for SerializableUrl { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - let string_representation: String = try!(Deserialize::deserialize(deserializer)); - Ok(SerializableUrl(FromStr::from_str(&string_representation[..]).unwrap())) - } -} - -#[derive(Clone, PartialEq)] -pub struct SerializableContentType(pub ContentType); - -impl Deref for SerializableContentType { - type Target = ContentType; - - fn deref(&self) -> &ContentType { - &self.0 - } -} - -impl Serialize for SerializableContentType { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - format!("{}", self.0).serialize(serializer) - } -} - -impl Deserialize for SerializableContentType { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - let string_representation: String = try!(Deserialize::deserialize(deserializer)); - Ok(SerializableContentType(Header::parse_header( - &[string_representation.into_bytes()]).unwrap())) - } -} - -#[derive(Clone, PartialEq)] -pub struct SerializableRawStatus(pub RawStatus); - -impl Deref for SerializableRawStatus { - type Target = RawStatus; - - fn deref(&self) -> &RawStatus { - &self.0 - } -} - -impl Serialize for SerializableRawStatus { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - ((self.0).0, (self.0).1.clone().into_owned()).serialize(serializer) - } -} - -impl Deserialize for SerializableRawStatus { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - let representation: (u16, String) = try!(Deserialize::deserialize(deserializer)); - Ok(SerializableRawStatus(RawStatus(representation.0, Cow::Owned(representation.1)))) - } -} - -#[derive(Clone, PartialEq, Debug)] -pub struct SerializableStringResult(pub Result<(),String>); - -#[derive(Deserialize, Serialize)] -enum SerializableStringResultInternal { - Ok(()), - Err(String), -} - -impl Deref for SerializableStringResult { - type Target = Result<(),String>; - - fn deref(&self) -> &Result<(),String> { - &self.0 - } -} - -impl Serialize for SerializableStringResult { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - let result = match **self { - Ok(ref value) => SerializableStringResultInternal::Ok(*value), - Err(ref value) => SerializableStringResultInternal::Err((*value).clone()), - }; - result.serialize(serializer) - } -} - -impl Deserialize for SerializableStringResult { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - let result: SerializableStringResultInternal = - try!(Deserialize::deserialize(deserializer)); - match result { - SerializableStringResultInternal::Ok(value) => Ok(SerializableStringResult(Ok(value))), - SerializableStringResultInternal::Err(value) => { - Ok(SerializableStringResult(Err(value))) - } - } - } -} - diff --git a/components/profile_traits/Cargo.toml b/components/profile_traits/Cargo.toml index f85223c99ee..6cdf18b2b38 100644 --- a/components/profile_traits/Cargo.toml +++ b/components/profile_traits/Cargo.toml @@ -10,9 +10,12 @@ path = "lib.rs" [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] serde = "0.4" serde_macros = "0.4" time = "0.1.12" -url = "0.2.36" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index f079fafe1ab..97ecdb8e70a 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -76,7 +76,7 @@ rustc-serialize = "0.3" libc = "0.1" unicase = "0.1" num = "0.1.24" -websocket = "0.12" +websocket = "0.12.0" uuid = "0.1.16" smallvec = "0.1" html5ever = { version = "0.2.1", features = ["unstable"] } diff --git a/components/script/cors.rs b/components/script/cors.rs index e2ecb1da5cb..b1a1e56cb02 100644 --- a/components/script/cors.rs +++ b/components/script/cors.rs @@ -11,13 +11,11 @@ use network_listener::{NetworkListener, PreInvoke}; use script_task::ScriptChan; -use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction, Metadata}; -use net_traits::{SerializableStringResult}; +use net_traits::{AsyncResponseListener, ResponseAction, Metadata}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::RefCell; -use std::sync::mpsc; use std::sync::{Arc, Mutex}; use time; use time::{now, Timespec}; @@ -133,14 +131,9 @@ impl CORSRequest { listener: listener, response: RefCell::new(None), }; - let (action_sender, action_receiver) = mpsc::channel(); let listener = NetworkListener { context: Arc::new(Mutex::new(context)), script_chan: script_chan, - receiver: action_receiver, - }; - let response_target = AsyncResponseTarget { - sender: action_sender, }; // TODO: this exists only to make preflight check non-blocking @@ -151,8 +144,7 @@ impl CORSRequest { let mut context = listener.context.lock(); let context = context.as_mut().unwrap(); *context.response.borrow_mut() = Some(response); - response_target.invoke_with_listener(ResponseAction::ResponseComplete( - SerializableStringResult(Ok(())))); + listener.notify(ResponseAction::ResponseComplete(Ok(()))); }); } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 741921af652..258d53dc6bc 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -45,7 +45,7 @@ use euclid::size::Size2D; use html5ever::tree_builder::QuirksMode; use hyper::header::Headers; use hyper::method::Method; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{IpcReceiver, IpcSender}; use js::jsapi::{JSObject, JSTracer, JSGCTraceKind, JS_CallValueTracer, JS_CallObjectTracer, GCTraceKindToAscii, Heap}; use js::jsapi::JS_CallUnbarrieredObjectTracer; use js::jsval::JSVal; @@ -57,6 +57,7 @@ use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask}; use net_traits::storage_task::StorageType; use script_traits::ScriptControlChan; use script_traits::UntrustedNodeAddress; +use serde::{Serialize, Deserialize}; use smallvec::SmallVec; use msg::compositor_msg::ScriptListener; use msg::constellation_msg::ConstellationChan; @@ -356,9 +357,10 @@ impl JSTraceable for Box { } } -impl JSTraceable for () { +impl JSTraceable for IpcReceiver where T: Deserialize + Serialize { #[inline] - fn trace(&self, _trc: *mut JSTracer) { + fn trace(&self, _: *mut JSTracer) { + // Do nothing } } diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 02f75d3832b..5c44f5aff6a 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -181,7 +181,7 @@ impl DedicatedWorkerGlobalScope { let serialized_url = url.serialize(); let parent_sender_for_reporter = parent_sender.clone(); let global = DedicatedWorkerGlobalScope::new( - url.0, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), + url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), resource_task, constellation_chan, parent_sender, own_sender, receiver); // FIXME(njn): workers currently don't have a unique ID suitable for using in reporter // registration (#6631), so we instead use a random number and cross our fingers. diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 31800bcc014..dd7dc90e0fe 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -74,7 +74,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyMod use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL}; use net_traits::CookieSource::NonHTTP; use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; -use net_traits::{Metadata, PendingAsyncLoad, AsyncResponseTarget, SerializableUrl}; +use net_traits::{Metadata, PendingAsyncLoad, AsyncResponseTarget}; use script_task::Runnable; use script_traits::{MouseButton, UntrustedNodeAddress}; use util::opts; @@ -83,6 +83,7 @@ use layout_interface::{ReflowGoal, ReflowQueryType}; use euclid::point::Point2D; use html5ever::tree_builder::{QuirksMode, NoQuirks, LimitedQuirks, Quirks}; +use ipc_channel::ipc; use layout_interface::{LayoutChan, Msg}; use string_cache::{Atom, QualName}; use url::Url; @@ -1720,10 +1721,8 @@ impl<'a> DocumentMethods for &'a Document { return Err(Security); } let window = self.window.root(); - let (tx, rx) = channel(); - let _ = window.r().resource_task().send(GetCookiesForUrl(SerializableUrl(url), - tx, - NonHTTP)); + let (tx, rx) = ipc::channel().unwrap(); + let _ = window.r().resource_task().send(GetCookiesForUrl(url, tx, NonHTTP)); let cookies = rx.recv().unwrap(); Ok(cookies.unwrap_or("".to_owned())) } @@ -1736,9 +1735,7 @@ impl<'a> DocumentMethods for &'a Document { return Err(Security); } let window = self.window.root(); - let _ = window.r().resource_task().send(SetCookiesForUrl(SerializableUrl(url), - cookie, - NonHTTP)); + let _ = window.r().resource_task().send(SetCookiesForUrl(url, cookie, NonHTTP)); Ok(()) } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 8e28fa51b62..b4c8a5e4946 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -40,14 +40,14 @@ use js::jsval::UndefinedValue; use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{Encoding, EncodingRef, DecoderTrap}; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use net_traits::{Metadata, AsyncResponseListener, AsyncResponseTarget}; use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; use html5ever::tree_builder::NextParserState; use std::cell::{RefCell, Cell}; use std::mem; -use std::sync::mpsc; use std::sync::{Arc, Mutex}; -use std::thread; use string_cache::Atom; use url::{Url, UrlParser}; @@ -332,16 +332,17 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement { url: url.clone(), })); - let (action_sender, action_receiver) = mpsc::channel(); + let (action_sender, action_receiver) = ipc::channel().unwrap(); let listener = box NetworkListener { context: context, script_chan: script_chan, - receiver: action_receiver, }; let response_target = AsyncResponseTarget { sender: action_sender, }; - thread::spawn(move || listener.run()); + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + listener.notify(message.to().unwrap()); + }); doc.r().load_async(LoadType::Script(url), response_target); @@ -400,7 +401,7 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement { // encoding as the fallback encoding. (UTF_8.decode(&*bytes, DecoderTrap::Replace).unwrap(), true, - metadata.final_url.0) + metadata.final_url) }, // Step 2.b.1.c. diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 6e12320b682..a81fe125973 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -84,7 +84,7 @@ impl ParserContext { impl AsyncResponseListener for ParserContext { fn headers_available(&self, metadata: Metadata) { - let content_type = metadata.content_type.clone().map(|content_type| content_type.0); + let content_type = metadata.content_type.clone(); let parser = ScriptTask::page_fetch_complete(self.id.clone(), self.subpage.clone(), metadata); diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index ed4bfe1a705..980683114a2 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -46,20 +46,21 @@ use js::jsval::{JSVal, NullValue, UndefinedValue}; use net_traits::ControlMsg::Load; use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadConsumer}; -use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, SerializableHeaders}; -use net_traits::{SerializableMethod, SerializableUrl}; +use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata}; use cors::{allow_cross_origin_request, CORSRequest, RequestMode, AsyncCORSResponseListener}; use cors::CORSResponse; use util::str::DOMString; use util::task::spawn_named; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::{RefCell, Cell}; use std::default::Default; use std::sync::{Mutex, Arc}; use std::sync::mpsc::{channel, Sender, TryRecvError}; -use std::thread::{self, sleep_ms}; +use std::thread::sleep_ms; use time; use url::{Url, UrlParser}; @@ -217,7 +218,7 @@ impl XMLHttpRequest { let mut load_data = self.load_data.borrow_mut().take().unwrap(); load_data.cors = Some(ResourceCORSData { preflight: self.req.preflight_flag, - origin: SerializableUrl(self.req.origin.clone()) + origin: self.req.origin.clone() }); XMLHttpRequest::initiate_async_xhr(self.xhr.clone(), self.script_chan.clone(), @@ -271,16 +272,17 @@ impl XMLHttpRequest { } } - let (action_sender, action_receiver) = channel(); + let (action_sender, action_receiver) = ipc::channel().unwrap(); let listener = box NetworkListener { context: context, script_chan: script_chan, - receiver: action_receiver, }; let response_target = AsyncResponseTarget { sender: action_sender, }; - thread::spawn(move || listener.run()); + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + listener.notify(message.to().unwrap()); + }); resource_task.send(Load(load_data, LoadConsumer::Listener(response_target))).unwrap(); } } @@ -546,15 +548,14 @@ impl<'a> XMLHttpRequestMethods for &'a XMLHttpRequest { None => () } - load_data.preserved_headers = - SerializableHeaders((*self.request_headers.borrow()).clone()); + load_data.preserved_headers = (*self.request_headers.borrow()).clone(); if !load_data.preserved_headers.has::() { let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]); load_data.preserved_headers.set(Accept(vec![qitem(mime)])); } - load_data.method = SerializableMethod((*self.request_method.borrow()).clone()); + load_data.method = (*self.request_method.borrow()).clone(); // CORS stuff let global = self.global.root(); @@ -564,12 +565,12 @@ impl<'a> XMLHttpRequestMethods for &'a XMLHttpRequest { } else { RequestMode::CORS }; - let mut combined_headers = (*load_data.headers).clone(); + let mut combined_headers = load_data.headers.clone(); combined_headers.extend(load_data.preserved_headers.iter()); let cors_request = CORSRequest::maybe_new(referer_url.clone(), - (*load_data.url).clone(), + load_data.url.clone(), mode, - (*load_data.method).clone(), + load_data.method.clone(), combined_headers); match cors_request { Ok(None) => { @@ -791,10 +792,9 @@ impl<'a> PrivateXMLHttpRequestHelpers for &'a XMLHttpRequest { _ => {} }; // XXXManishearth Clear cache entries in case of a network error - self.process_partial_response(XHRProgress::HeadersReceived( - gen_id, - metadata.headers.map(|headers| headers.0), - metadata.status.map(|status| status.0))); + self.process_partial_response(XHRProgress::HeadersReceived(gen_id, + metadata.headers, + metadata.status)); Ok(()) } diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index 2abff122309..cd69b3a030f 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -4,7 +4,6 @@ use script_task::{ScriptChan, ScriptMsg, Runnable}; use net_traits::{AsyncResponseListener, ResponseAction}; -use std::sync::mpsc::Receiver; use std::sync::{Arc, Mutex}; /// An off-thread sink for async network event runnables. All such events are forwarded to @@ -12,17 +11,14 @@ use std::sync::{Arc, Mutex}; pub struct NetworkListener { pub context: Arc>, pub script_chan: Box, - pub receiver: Receiver, } impl NetworkListener { - pub fn run(&self) { - while let Ok(action) = self.receiver.recv() { - self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { - context: self.context.clone(), - action: action, - })).unwrap(); - } + pub fn notify(&self, action: ResponseAction) { + self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { + context: self.context.clone(), + action: action, + })).unwrap(); } } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index fab0908683c..46796d76dbd 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -69,8 +69,6 @@ use msg::constellation_msg::Msg as ConstellationMsg; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; use net_traits::{AsyncResponseTarget, ResourceTask, LoadConsumer, ControlMsg, Metadata}; -use net_traits::{SerializableContentType, SerializableHeaders, SerializableMethod}; -use net_traits::{SerializableUrl}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult}; use net_traits::storage_task::StorageTask; use profile_traits::mem::{self, Report, Reporter, ReporterRequest, ReportKind, ReportsChan}; @@ -105,7 +103,6 @@ use std::rc::Rc; use std::result::Result; use std::sync::{Arc, Mutex}; use std::sync::mpsc::{channel, Sender, Receiver, Select}; -use std::thread; use time::Tm; use hyper::header::{ContentType, HttpDate}; @@ -1312,7 +1309,7 @@ impl ScriptTask { /// The entry point to document loading. Defines bindings, sets up the window and document /// objects, parses HTML and CSS, and kicks off initial layout. fn load(&self, metadata: Metadata, incomplete: InProgressLoad) -> Root { - let final_url = (*metadata.final_url).clone(); + let final_url = metadata.final_url.clone(); debug!("ScriptTask: loading {} on page {:?}", incomplete.url.serialize(), incomplete.pipeline_id); // We should either be initializing a root page or loading a child page of an @@ -1418,9 +1415,7 @@ impl ScriptTask { }); let content_type = match metadata.content_type { - Some(SerializableContentType(ContentType(Mime(TopLevel::Text, - SubLevel::Plain, - _)))) => { + Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => { Some("text/plain".to_owned()) } _ => None @@ -1687,13 +1682,14 @@ impl ScriptTask { let context = Arc::new(Mutex::new(ParserContext::new(id, subpage, script_chan.clone(), load_data.url.clone()))); - let (action_sender, action_receiver) = channel(); + let (action_sender, action_receiver) = ipc::channel().unwrap(); let listener = box NetworkListener { context: context, script_chan: script_chan.clone(), - receiver: action_receiver, }; - thread::spawn(move || listener.run()); + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + listener.notify(message.to().unwrap()); + }); let response_target = AsyncResponseTarget { sender: action_sender, }; @@ -1703,10 +1699,10 @@ impl ScriptTask { } resource_task.send(ControlMsg::Load(NetLoadData { - url: SerializableUrl(load_data.url), - method: SerializableMethod(load_data.method), - headers: SerializableHeaders(Headers::new()), - preserved_headers: SerializableHeaders(load_data.headers), + url: load_data.url, + method: load_data.method, + headers: Headers::new(), + preserved_headers: load_data.headers, data: load_data.data, cors: None, pipeline_id: Some(id), diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index d902192f700..ddd29bbb524 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -25,8 +25,11 @@ path = "../devtools_traits" [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] -url = "0.2.36" libc = "0.1" euclid = "0.1" serde = "0.4" diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 8415a423b61..7c969ece482 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -910,6 +910,7 @@ version = "0.0.1" dependencies = [ "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "net 0.0.1", "net_traits 0.0.1", "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index b96b734147e..00a30da7962 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -100,9 +100,12 @@ optional = true path = "../../support/android-rs-glue/glue" optional = true +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] env_logger = "0.3" -url = "0.2.36" time = "0.1.12" bitflags = "0.3" libc = "0.1" diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 79259bfb392..110deb31879 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -23,13 +23,16 @@ features = ["unstable"] version = "0.3" features = [ "serde-serialization" ] +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" encoding = "0.2" fnv = "1.0" rustc-serialize = "0.3" matches = "0.1" -url = "0.2.36" bitflags = "0.3" num = "0.1.24" lazy_static = "0.1.10" diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 6558792b21b..4d9027653f9 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -28,6 +28,10 @@ features = [ "serde-serialization" ] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" bitflags = "0.3" @@ -37,7 +41,6 @@ rustc-serialize = "0.3" smallvec = "0.1" num_cpus = "0.2.2" num = "0.1.24" -url = "0.2.36" euclid = "0.1" serde = "0.4" serde_macros = "0.4" diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index 7fb28951fb8..61a7f2ba361 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -23,8 +23,11 @@ features = [ "serde-serialization" ] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" +[dependencies.url] +version = "0.2" +features = [ "serde_serialization" ] + [dependencies] log = "0.3" rustc-serialize = "0.3.4" -url = "0.2.36" uuid = "0.1" diff --git a/tests/unit/net/Cargo.toml b/tests/unit/net/Cargo.toml index 5e9608356c7..62c72b975bc 100644 --- a/tests/unit/net/Cargo.toml +++ b/tests/unit/net/Cargo.toml @@ -17,6 +17,9 @@ path = "../../../components/net_traits" [dependencies.util] path = "../../../components/util" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] cookie = "0.1" hyper = "0.6" diff --git a/tests/unit/net/data_loader.rs b/tests/unit/net/data_loader.rs index 362fd4c5193..702083798a5 100644 --- a/tests/unit/net/data_loader.rs +++ b/tests/unit/net/data_loader.rs @@ -4,6 +4,7 @@ extern crate hyper; +use ipc_channel::ipc; use net_traits::LoadConsumer::Channel; use net_traits::LoadData; use net_traits::ProgressMsg::{Payload, Done}; @@ -19,7 +20,7 @@ fn assert_parse(url: &'static str, use url::Url; use net::data_loader::load; - let (start_chan, start_port) = channel(); + let (start_chan, start_port) = ipc::channel().unwrap(); load(LoadData::new(Url::parse(url).unwrap(), None), Channel(start_chan)); let response = start_port.recv().unwrap(); diff --git a/tests/unit/net/lib.rs b/tests/unit/net/lib.rs index d9d0f05a79f..3f737fc1783 100644 --- a/tests/unit/net/lib.rs +++ b/tests/unit/net/lib.rs @@ -4,6 +4,7 @@ #![cfg_attr(test, feature(box_raw))] +extern crate ipc_channel; extern crate net; extern crate net_traits; extern crate url; diff --git a/tests/unit/net/resource_task.rs b/tests/unit/net/resource_task.rs index 989558c2f21..05b719373ea 100644 --- a/tests/unit/net/resource_task.rs +++ b/tests/unit/net/resource_task.rs @@ -2,9 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net::resource_task::new_resource_task; -use net::resource_task::parse_hostsfile; -use net::resource_task::replace_hosts; +use ipc_channel::ipc; +use net::resource_task::{new_resource_task, parse_hostsfile, replace_hosts}; use net_traits::{ControlMsg, LoadData, LoadConsumer}; use net_traits::ProgressMsg; use std::borrow::ToOwned; @@ -21,7 +20,7 @@ fn test_exit() { #[test] fn test_bad_scheme() { let resource_task = new_resource_task(None, None); - let (start_chan, start) = channel(); + let (start_chan, start) = ipc::channel().unwrap(); let url = Url::parse("bogus://whatever").unwrap(); resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(start_chan))).unwrap(); let response = start.recv().unwrap(); @@ -170,7 +169,7 @@ fn test_replace_hosts() { //Start the resource task and make a request to our TCP server let resource_task = new_resource_task(None, None); - let (start_chan, _) = channel(); + let (start_chan, _start_port) = ipc::channel().unwrap(); let url = Url::parse(&format!("http://foo.bar.com:{}", port)).unwrap(); let msg = ControlMsg::Load(replace_hosts(LoadData::new(url, None), host_table), LoadConsumer::Channel(start_chan)); From 024c4df912a01be6d2909f4402ad2791f53e0dce Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 30 Jul 2015 22:35:12 -0700 Subject: [PATCH 4/5] script: Fix merge fallout. --- components/net/resource_task.rs | 10 +++++----- components/net_traits/Cargo.toml | 4 ---- components/script/dom/bindings/trace.rs | 8 +++++++- tests/unit/net/hsts.rs | 3 ++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index 70c0ec71a4b..1ccd09d6219 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -250,7 +250,7 @@ impl ResourceChannelManager { } } -struct ResourceManager { +pub struct ResourceManager { user_agent: Option, cookie_storage: CookieStorage, resource_task: IpcSender, @@ -260,10 +260,10 @@ struct ResourceManager { } impl ResourceManager { - fn new(user_agent: Option, - resource_task: IpcSender, - hsts_list: HSTSList, - devtools_channel: Option>) -> ResourceManager { + pub fn new(user_agent: Option, + resource_task: IpcSender, + hsts_list: HSTSList, + devtools_channel: Option>) -> ResourceManager { ResourceManager { user_agent: user_agent, cookie_storage: CookieStorage::new(), diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index fbed03472d3..5ca00f82ce5 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -24,10 +24,6 @@ git = "https://github.com/servo/rust-stb-image" version = "0.6" features = [ "serde-serialization" ] -[dependencies.url] -version = "0.2.36" -features = [ "serde_serialization" ] - [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 258d53dc6bc..770515cce40 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -65,7 +65,6 @@ use net_traits::image::base::Image; use profile_traits::mem::ProfilerChan; use util::str::{LengthOrPercentageOrAuto}; use selectors::parser::PseudoElement; -use serde::{Deserialize, Serialize}; use std::cell::{Cell, UnsafeCell, RefCell}; use std::collections::{HashMap, HashSet}; use std::collections::hash_state::HashState; @@ -357,6 +356,13 @@ impl JSTraceable for Box { } } +impl JSTraceable for () { + #[inline] + fn trace(&self, _: *mut JSTracer) { + // Do nothing + } +} + impl JSTraceable for IpcReceiver where T: Deserialize + Serialize { #[inline] fn trace(&self, _: *mut JSTracer) { diff --git a/tests/unit/net/hsts.rs b/tests/unit/net/hsts.rs index 56deee0927f..7ac11d4dbc3 100644 --- a/tests/unit/net/hsts.rs +++ b/tests/unit/net/hsts.rs @@ -7,6 +7,7 @@ use net::hsts::HSTSEntry; use net_traits::IncludeSubdomains; use net::hsts::{secure_url, preload_hsts_domains}; use net::resource_task::ResourceManager; +use ipc_channel::ipc; use std::sync::mpsc::channel; use url::Url; use time; @@ -17,7 +18,7 @@ fn test_add_hsts_entry_to_resource_manager_adds_an_hsts_entry() { entries: Vec::new() }; - let (tx, _) = channel(); + let (tx, _) = ipc::channel().unwrap(); let mut manager = ResourceManager::new(None, tx, list, None); let entry = HSTSEntry::new( From 61e3a9545ecd3b93e275af6dfa425a7fdd42f9db Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 31 Jul 2015 11:48:47 -0700 Subject: [PATCH 5/5] script: Fix test failures. --- components/script/document_loader.rs | 11 ++++++++--- components/script/dom/bindings/global.rs | 2 +- components/script/dom/window.rs | 9 +++++---- components/script/network_listener.rs | 6 ++++-- components/script/script_task.rs | 9 +++++---- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 439fc98367a..56ee98bdbbf 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -9,6 +9,7 @@ use script_task::{ScriptMsg, ScriptChan}; use msg::constellation_msg::{PipelineId}; use net_traits::{Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad}; use net_traits::AsyncResponseTarget; +use std::sync::Arc; use url::Url; #[derive(JSTraceable, PartialEq, Clone, Debug)] @@ -34,7 +35,9 @@ impl LoadType { #[derive(JSTraceable)] pub struct DocumentLoader { - pub resource_task: ResourceTask, + /// We use an `Arc` here in order to avoid file descriptor exhaustion when there + /// are lots of iframes. + pub resource_task: Arc, notifier_data: Option, blocking_loads: Vec, } @@ -50,7 +53,9 @@ impl DocumentLoader { DocumentLoader::new_with_task(existing.resource_task.clone(), None, None) } - pub fn new_with_task(resource_task: ResourceTask, + /// We use an `Arc` here in order to avoid file descriptor exhaustion when there + /// are lots of iframes. + pub fn new_with_task(resource_task: Arc, data: Option, initial_load: Option,) -> DocumentLoader { @@ -69,7 +74,7 @@ impl DocumentLoader { let url = load.url().clone(); self.blocking_loads.push(load); let pipeline = self.notifier_data.as_ref().map(|data| data.pipeline); - PendingAsyncLoad::new(self.resource_task.clone(), url, pipeline) + PendingAsyncLoad::new((*self.resource_task).clone(), url, pipeline) } /// Create and initiate a new network request. diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 5f0f7668af4..cfdd3df4af5 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -116,7 +116,7 @@ impl<'a> GlobalRef<'a> { let doc = window.Document(); let doc = doc.r(); let loader = doc.loader(); - loader.resource_task.clone() + (*loader.resource_task).clone() } GlobalRef::Worker(ref worker) => worker.resource_task().clone(), } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index d4f2a36eabf..d7a9e9f243a 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -74,8 +74,9 @@ use std::default::Default; use std::ffi::CString; use std::mem as std_mem; use std::rc::Rc; -use std::sync::mpsc::{channel, Receiver}; +use std::sync::Arc; use std::sync::mpsc::TryRecvError::{Empty, Disconnected}; +use std::sync::mpsc::{channel, Receiver}; use time; /// Current state of the window object @@ -173,7 +174,7 @@ pub struct Window { window_size: Cell>, /// Associated resource task for use by DOM objects like XMLHttpRequest - resource_task: ResourceTask, + resource_task: Arc, /// A handle for communicating messages to the storage task. storage_task: StorageTask, @@ -883,7 +884,7 @@ impl<'a> WindowHelpers for &'a Window { } fn resource_task(self) -> ResourceTask { - self.resource_task.clone() + (*self.resource_task).clone() } fn mem_profiler_chan(self) -> mem::ProfilerChan { @@ -1035,7 +1036,7 @@ impl Window { control_chan: ScriptControlChan, compositor: ScriptListener, image_cache_task: ImageCacheTask, - resource_task: ResourceTask, + resource_task: Arc, storage_task: StorageTask, mem_profiler_chan: mem::ProfilerChan, devtools_chan: Option>, diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index cd69b3a030f..7ede86e0742 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -15,10 +15,12 @@ pub struct NetworkListener NetworkListener { pub fn notify(&self, action: ResponseAction) { - self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { + if let Err(err) = self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { context: self.context.clone(), action: action, - })).unwrap(); + })) { + warn!("failed to deliver network data: {:?}", err); + } } } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 46796d76dbd..bf23bca2db6 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -287,8 +287,9 @@ pub struct ScriptTask { incomplete_loads: DOMRefCell>, /// A handle to the image cache task. image_cache_task: ImageCacheTask, - /// A handle to the resource task. - resource_task: ResourceTask, + /// A handle to the resource task. This is an `Arc` to avoid running out of file descriptors if + /// there are many iframes. + resource_task: Arc, /// A handle to the storage task. storage_task: StorageTask, @@ -418,7 +419,7 @@ impl ScriptTaskFactory for ScriptTask { control_chan, control_port, constellation_chan, - resource_task, + Arc::new(resource_task), storage_task, image_cache_task, mem_profiler_chan.clone(), @@ -504,7 +505,7 @@ impl ScriptTask { control_chan: ScriptControlChan, control_port: Receiver, constellation_chan: ConstellationChan, - resource_task: ResourceTask, + resource_task: Arc, storage_task: StorageTask, image_cache_task: ImageCacheTask, mem_profiler_chan: mem::ProfilerChan,