1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use filemanager_thread::FileManager;
6 use hyper::header::{Charset, ContentLength, ContentType, Headers};
7 use hyper::header::{ContentDisposition, DispositionParam, DispositionType};
8 use ipc_channel::ipc;
9 use mime::{Attr, Mime};
10 use net_traits::NetworkError;
11 use net_traits::blob_url_store::parse_blob_url;
12 use net_traits::filemanager_thread::ReadFileProgress;
13 use servo_url::ServoUrl;
14
15 // TODO: Check on GET
16 // https://w3c.github.io/FileAPI/#requestResponseModel
17
18 /// https://fetch.spec.whatwg.org/#concept-basic-fetch (partial)
19 // TODO: make async.
load_blob_sync(url: ServoUrl, filemanager: FileManager) -> Result<(Headers, Vec<u8>), NetworkError>20 pub fn load_blob_sync
21 (url: ServoUrl,
22 filemanager: FileManager)
23 -> Result<(Headers, Vec<u8>), NetworkError> {
24 let (id, origin) = match parse_blob_url(&url) {
25 Ok((id, origin)) => (id, origin),
26 Err(()) => {
27 let e = format!("Invalid blob URL format {:?}", url);
28 return Err(NetworkError::Internal(e));
29 }
30 };
31
32 let (sender, receiver) = ipc::channel().unwrap();
33 let check_url_validity = true;
34 filemanager.read_file(sender, id, check_url_validity, origin);
35
36 let blob_buf = match receiver.recv().unwrap() {
37 Ok(ReadFileProgress::Meta(blob_buf)) => blob_buf,
38 Ok(_) => {
39 return Err(NetworkError::Internal("Invalid filemanager reply".to_string()));
40 }
41 Err(e) => {
42 return Err(NetworkError::Internal(format!("{:?}", e)));
43 }
44 };
45
46 let content_type: Mime = blob_buf.type_string.parse().unwrap_or(mime!(Text / Plain));
47 let charset = content_type.get_param(Attr::Charset);
48
49 let mut headers = Headers::new();
50
51 if let Some(name) = blob_buf.filename {
52 let charset = charset.and_then(|c| c.as_str().parse().ok());
53 headers.set(ContentDisposition {
54 disposition: DispositionType::Inline,
55 parameters: vec![
56 DispositionParam::Filename(charset.unwrap_or(Charset::Us_Ascii),
57 None, name.as_bytes().to_vec())
58 ]
59 });
60 }
61
62 // Basic fetch, Step 4.
63 headers.set(ContentLength(blob_buf.size as u64));
64 // Basic fetch, Step 5.
65 headers.set(ContentType(content_type.clone()));
66
67 let mut bytes = blob_buf.bytes;
68 loop {
69 match receiver.recv().unwrap() {
70 Ok(ReadFileProgress::Partial(ref mut new_bytes)) => {
71 bytes.append(new_bytes);
72 }
73 Ok(ReadFileProgress::EOF) => {
74 return Ok((headers, bytes));
75 }
76 Ok(_) => {
77 return Err(NetworkError::Internal("Invalid filemanager reply".to_string()));
78 }
79 Err(e) => {
80 return Err(NetworkError::Internal(format!("{:?}", e)));
81 }
82 }
83 }
84 }
85