diff options
author | Ms2ger <Ms2ger@gmail.com> | 2016-10-13 17:01:24 +0200 |
---|---|---|
committer | Ms2ger <Ms2ger@gmail.com> | 2016-10-14 14:18:03 +0200 |
commit | e134871a95c43e4938fddb48b5b8398f896178ed (patch) | |
tree | a3d8334d91f777231b617d0ae42b252392a23116 /components/net/blob_loader.rs | |
parent | 92f1cbcbe3550c3456e5db873c80ef086b72991a (diff) | |
download | servo-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.rs | 70 |
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))); + } + } + } +} |