aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/data_loader.rs
diff options
context:
space:
mode:
authorRahul Sharma <rsconceptx@gmail.com>2016-03-29 21:54:19 +0530
committerRahul Sharma <rsconceptx@gmail.com>2016-04-01 09:49:08 +0530
commit3e74164e5f79a2eb177f778c7f8bedb72514673f (patch)
tree4dea6aa8e51233e02a565b142c1dcc12fa05e7b3 /components/net/data_loader.rs
parent9a8d62286c6556fca7471f2db37f896174bc4d9e (diff)
downloadservo-3e74164e5f79a2eb177f778c7f8bedb72514673f.tar.gz
servo-3e74164e5f79a2eb177f778c7f8bedb72514673f.zip
implements data-url fetching
Diffstat (limited to 'components/net/data_loader.rs')
-rw-r--r--components/net/data_loader.rs59
1 files changed, 38 insertions, 21 deletions
diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs
index f8386451deb..50452302627 100644
--- a/components/net/data_loader.rs
+++ b/components/net/data_loader.rs
@@ -4,12 +4,14 @@
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use mime_classifier::MIMEClassifier;
-use net_traits::ProgressMsg::{Done, Payload};
-use net_traits::{LoadConsumer, LoadData, Metadata};
+use net_traits::LoadConsumer;
+use net_traits::ProgressMsg::{Payload, Done};
+use net_traits::{LoadData, Metadata};
use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt};
use rustc_serialize::base64::FromBase64;
use std::sync::Arc;
use url::SchemeData;
+use url::Url;
use url::percent_encoding::percent_decode;
pub fn factory(load_data: LoadData,
@@ -23,17 +25,19 @@ pub fn factory(load_data: LoadData,
load(load_data, senders, classifier, cancel_listener)
}
-pub fn load(load_data: LoadData,
- start_chan: LoadConsumer,
- classifier: Arc<MIMEClassifier>,
- cancel_listener: CancellationListener) {
- let url = load_data.url;
- assert!(&*url.scheme == "data");
+pub enum DecodeError {
+ InvalidDataUri,
+ NonBase64DataUri,
+}
+pub type DecodeData = (Mime, Vec<u8>);
+
+pub fn decode(url: &Url) -> Result<DecodeData, DecodeError> {
+ assert!(&*url.scheme == "data");
// Split out content type and data.
let mut scheme_data = match url.scheme_data {
SchemeData::NonRelative(ref scheme_data) => scheme_data.clone(),
- _ => panic!("Expected a non-relative scheme URL.")
+ _ => panic!("Expected a non-relative scheme URL."),
};
match url.query {
Some(ref query) => {
@@ -44,8 +48,7 @@ pub fn load(load_data: LoadData,
}
let parts: Vec<&str> = scheme_data.splitn(2, ',').collect();
if parts.len() != 2 {
- send_error(url, "invalid data uri".to_owned(), start_chan);
- return;
+ return Err(DecodeError::InvalidDataUri);
}
// ";base64" must come at the end of the content type, per RFC 2397.
@@ -69,31 +72,45 @@ pub fn load(load_data: LoadData,
vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))));
}
- if cancel_listener.is_cancelled() {
- return;
- }
-
let bytes = percent_decode(parts[1].as_bytes());
let bytes = if is_base64 {
// FIXME(#2909): It’s unclear what to do with non-alphabet characters,
// but Acid 3 apparently depends on spaces being ignored.
let bytes = bytes.into_iter().filter(|&b| b != ' ' as u8).collect::<Vec<u8>>();
match bytes.from_base64() {
- Err(..) => return send_error(url, "non-base64 data uri".to_owned(), start_chan),
+ Err(..) => return Err(DecodeError::NonBase64DataUri),
Ok(data) => data,
}
} else {
bytes
};
+ Ok((content_type.unwrap(), bytes))
+}
- let mut metadata = Metadata::default(url);
- metadata.set_content_type(content_type.as_ref());
- if let Ok(chan) = start_sending_sniffed_opt(start_chan,
+pub fn load(load_data: LoadData,
+ start_chan: LoadConsumer,
+ classifier: Arc<MIMEClassifier>,
+ cancel_listener: CancellationListener) {
+ let url = load_data.url;
+
+ if cancel_listener.is_cancelled() {
+ return;
+ }
+
+ match decode(&url) {
+ Ok((content_type, bytes)) => {
+ let mut metadata = Metadata::default(url);
+ metadata.set_content_type(Some(content_type).as_ref());
+ if let Ok(chan) = start_sending_sniffed_opt(start_chan,
metadata,
classifier,
&bytes,
load_data.context) {
- let _ = chan.send(Payload(bytes));
- let _ = chan.send(Done(Ok(())));
+ let _ = chan.send(Payload(bytes));
+ let _ = chan.send(Done(Ok(())));
+ }
+ },
+ Err(DecodeError::InvalidDataUri) => send_error(url, "invalid data uri".to_owned(), start_chan),
+ Err(DecodeError::NonBase64DataUri) => send_error(url, "non-base64 data uri".to_owned(), start_chan),
}
}