aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/blob_loader.rs
diff options
context:
space:
mode:
authorMs2ger <Ms2ger@gmail.com>2016-10-13 17:01:24 +0200
committerMs2ger <Ms2ger@gmail.com>2016-10-14 14:18:03 +0200
commite134871a95c43e4938fddb48b5b8398f896178ed (patch)
treea3d8334d91f777231b617d0ae42b252392a23116 /components/net/blob_loader.rs
parent92f1cbcbe3550c3456e5db873c80ef086b72991a (diff)
downloadservo-e134871a95c43e4938fddb48b5b8398f896178ed.tar.gz
servo-e134871a95c43e4938fddb48b5b8398f896178ed.zip
Implement blob url support in the fetch stack.
Diffstat (limited to 'components/net/blob_loader.rs')
-rw-r--r--components/net/blob_loader.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/components/net/blob_loader.rs b/components/net/blob_loader.rs
index bb9537e48dd..9bd4eec04c9 100644
--- a/components/net/blob_loader.rs
+++ b/components/net/blob_loader.rs
@@ -18,6 +18,7 @@ use resource_thread::{send_error, start_sending_sniffed_opt};
use resource_thread::CancellationListener;
use std::boxed::FnBox;
use std::sync::Arc;
+use url::Url;
use util::thread::spawn_named;
// TODO: Check on GET
@@ -119,3 +120,72 @@ fn load_blob<UI: 'static + UIProvider>
send_error(load_data.url.clone(), format_err, start_chan);
}
}
+
+/// https://fetch.spec.whatwg.org/#concept-basic-fetch (partial)
+// TODO: make async.
+pub fn load_blob_sync<UI: 'static + UIProvider>
+ (url: Url,
+ filemanager: FileManager<UI>)
+ -> Result<(Headers, Vec<u8>), NetworkError> {
+ let (id, origin) = match parse_blob_url(&url) {
+ Ok((id, origin, _fragment)) => (id, origin),
+ Err(()) => {
+ let e = format!("Invalid blob URL format {:?}", url);
+ return Err(NetworkError::Internal(e));
+ }
+ };
+
+ let (sender, receiver) = ipc::channel().unwrap();
+ let check_url_validity = true;
+ let msg = FileManagerThreadMsg::ReadFile(sender, id, check_url_validity, origin);
+ let _ = filemanager.handle(msg, None);
+
+ let blob_buf = match receiver.recv().unwrap() {
+ Ok(ReadFileProgress::Meta(blob_buf)) => blob_buf,
+ Ok(_) => {
+ return Err(NetworkError::Internal("Invalid filemanager reply".to_string()));
+ }
+ Err(e) => {
+ return Err(NetworkError::Internal(format!("{:?}", e)));
+ }
+ };
+
+ let content_type: Mime = blob_buf.type_string.parse().unwrap_or(mime!(Text / Plain));
+ let charset = content_type.get_param(Attr::Charset);
+
+ let mut headers = Headers::new();
+
+ if let Some(name) = blob_buf.filename {
+ let charset = charset.and_then(|c| c.as_str().parse().ok());
+ headers.set(ContentDisposition {
+ disposition: DispositionType::Inline,
+ parameters: vec![
+ DispositionParam::Filename(charset.unwrap_or(Charset::Us_Ascii),
+ None, name.as_bytes().to_vec())
+ ]
+ });
+ }
+
+ // Basic fetch, Step 4.
+ headers.set(ContentLength(blob_buf.size as u64));
+ // Basic fetch, Step 5.
+ headers.set(ContentType(content_type.clone()));
+
+ let mut bytes = blob_buf.bytes;
+ loop {
+ match receiver.recv().unwrap() {
+ Ok(ReadFileProgress::Partial(ref mut new_bytes)) => {
+ bytes.append(new_bytes);
+ }
+ Ok(ReadFileProgress::EOF) => {
+ return Ok((headers, bytes));
+ }
+ Ok(_) => {
+ return Err(NetworkError::Internal("Invalid filemanager reply".to_string()));
+ }
+ Err(e) => {
+ return Err(NetworkError::Internal(format!("{:?}", e)));
+ }
+ }
+ }
+}