diff options
author | Jackson Lewis <st.japa6@gmail.com> | 2018-09-04 14:50:33 -0700 |
---|---|---|
committer | Jackson Lewis <st.japa6@gmail.com> | 2018-09-04 14:50:33 -0700 |
commit | 04288748ee1806dbf39e9d76e8cf2876dcf06015 (patch) | |
tree | 19b83877bd4cacf6c9fedb9c53571684124560c1 /components/net/fetch | |
parent | f04c965a9bab46ff6943416baab338032bc526c1 (diff) | |
download | servo-04288748ee1806dbf39e9d76e8cf2876dcf06015.tar.gz servo-04288748ee1806dbf39e9d76e8cf2876dcf06015.zip |
Make file fetch asynchronous
Diffstat (limited to 'components/net/fetch')
-rw-r--r-- | components/net/fetch/methods.rs | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index e36f0fcc86a..f81ee094a2e 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -27,10 +27,12 @@ use std::fmt; use std::fs::File; use std::io::{BufReader, BufRead}; use std::mem; +use std::sync::mpsc::channel; use std::str; use std::sync::{Arc, Mutex}; use std::sync::atomic::Ordering; use std::sync::mpsc::{Sender, Receiver}; +use std::thread; use subresource_integrity::is_response_integrity_valid; const FILE_CHUNK_SIZE: usize = 32768; //32 KB @@ -488,25 +490,51 @@ fn scheme_fetch(request: &mut Request, Ok(file_path) => { match File::open(file_path.clone()) { Ok(mut file) => { - let mut reader = BufReader::with_capacity(FILE_CHUNK_SIZE, file); - let mut bytes = Vec::new(); - loop { - let length = { - let mut buffer = reader.fill_buf().unwrap().to_vec(); - let buffer_len = buffer.len(); - bytes.append(&mut buffer); - target.process_response_chunk(buffer); - buffer_len - }; - if length == 0 { break; } - reader.consume(length); - } - let mime = guess_mime_type(file_path); let mut response = Response::new(url); - *response.body.lock().unwrap() = ResponseBody::Done(bytes); response.headers.set(ContentType(mime)); + + let (done_sender, done_receiver) = channel(); + *done_chan = Some((done_sender.clone(), done_receiver)); + *response.body.lock().unwrap() = ResponseBody::Receiving(vec![]); + + let mut res_body = response.body.clone(); + + let cancellation_listener = context.cancellation_listener.clone(); + + thread::Builder::new().name("fetch file worker thread".to_string()).spawn(move || { + let mut reader = BufReader::with_capacity(FILE_CHUNK_SIZE, file); + loop { + if cancellation_listener.lock().unwrap().cancelled() { + *res_body.lock().unwrap() = ResponseBody::Done(vec![]); + let _ = done_sender.send(Data::Cancelled); + return; + } + let length = { + let mut buffer = reader.fill_buf().unwrap().to_vec(); + let buffer_len = buffer.len(); + if let ResponseBody::Receiving(ref mut body) = *res_body.lock().unwrap() { + body.extend_from_slice(&buffer); + let _ = done_sender.send(Data::Payload(buffer.clone())); + } + buffer_len + }; + if length == 0 { + let mut body = res_body.lock().unwrap(); + let completed_body = match *body { + ResponseBody::Receiving(ref mut body) => { + mem::replace(body, vec![]) + }, + _ => vec![], + }; + *body = ResponseBody::Done(completed_body); + let _ = done_sender.send(Data::Done); + break; + } + reader.consume(length); + } + }).expect("Failed to create fetch file worker thread"); response }, _ => Response::network_error(NetworkError::Internal("Opening file failed".into())), |