diff options
Diffstat (limited to 'components/net/data_loader.rs')
-rw-r--r-- | components/net/data_loader.rs | 59 |
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), } } |