diff options
author | Zhen Zhang <izgzhen@gmail.com> | 2016-05-03 08:47:27 +0800 |
---|---|---|
committer | Zhen Zhang <izgzhen@gmail.com> | 2016-05-11 15:14:03 +0800 |
commit | c618ee21d0cca19631ebab9a1d735c48a0a7679a (patch) | |
tree | 4d4c8be52f78509cd4cf1a2f5f7ff1f30c1226c7 | |
parent | ab12d8098fcc0517b64643d25683e2e15e665410 (diff) | |
download | servo-c618ee21d0cca19631ebab9a1d735c48a0a7679a.tar.gz servo-c618ee21d0cca19631ebab9a1d735c48a0a7679a.zip |
add filemanager_thread
-rw-r--r-- | components/net/filemanager_thread.rs | 137 | ||||
-rw-r--r-- | components/net/lib.rs | 2 | ||||
-rw-r--r-- | components/net_traits/Cargo.toml | 1 | ||||
-rw-r--r-- | components/net_traits/filemanager_thread.rs | 34 | ||||
-rw-r--r-- | components/net_traits/lib.rs | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 2 |
8 files changed, 182 insertions, 0 deletions
diff --git a/components/net/filemanager_thread.rs b/components/net/filemanager_thread.rs new file mode 100644 index 00000000000..db9d87f86ac --- /dev/null +++ b/components/net/filemanager_thread.rs @@ -0,0 +1,137 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use net_traits::filemanager_thread::{FileManagerThreadMsg, FileManagerResult, FileManagerThreadError}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; +use std::path::{Path, PathBuf}; +use util::thread::spawn_named; +use uuid::Uuid; + +pub struct FileManager { + receiver: IpcReceiver<FileManagerThreadMsg>, + idmap: RefCell<HashMap<Uuid, PathBuf>>, +} + +impl FileManager { + fn new(recv: IpcReceiver<FileManagerThreadMsg>) -> FileManager { + FileManager { + receiver: recv, + idmap: RefCell::new(HashMap::new()), + } + } + + fn new_thread() -> IpcSender<FileManagerThreadMsg> { + let (chan, recv) = ipc::channel().unwrap(); + + spawn_named("FileManager".to_owned(), move || { + FileManager::new(recv).start(); + }); + + chan + } + + /// Start the file manager event loop + pub fn start(&mut self) { + loop { + match self.receiver.recv().unwrap() { + FileManagerThreadMsg::SelectFile(sender) => self.select_file(sender), + FileManagerThreadMsg::SelectFiles(sender) => self.select_files(sender), + FileManagerThreadMsg::ReadFile(sender, id) => self.read_file(sender, id), + FileManagerThreadMsg::DeleteFileID(id) => self.delete_fileid(id), + } + } + } +} + +impl FileManager { + fn select_file(&mut self, sender: IpcSender<FileManagerResult<(Uuid, PathBuf, u64)>>) { + // TODO: Pull the dialog UI in and get selected + let selected_path = Path::new(""); + + match self.create_entry(selected_path) { + Some(triple) => { + let _ = sender.send(Ok(triple)); + }, + None => { + let _ = sender.send(Err(FileManagerThreadError::InvalidSelection)); + } + } + } + + fn select_files(&mut self, sender: IpcSender<FileManagerResult<Vec<(Uuid, PathBuf, u64)>>>) { + let selected_paths = vec![Path::new("")]; + + let mut replies = vec![]; + + for path in selected_paths { + match self.create_entry(path) { + Some(triple) => replies.push(triple), + None => { + let _ = sender.send(Err(FileManagerThreadError::InvalidSelection)); + return; + } + } + } + + let _ = sender.send(Ok(replies)); + } + + fn create_entry(&mut self, file_path: &Path) -> Option<(Uuid, PathBuf, u64)> { + match File::open(file_path) { + Ok(handler) => { + let id = Uuid::new_v4(); + self.idmap.borrow_mut().insert(id, file_path.to_path_buf()); + + // Unix Epoch: https://doc.servo.org/std/time/constant.UNIX_EPOCH.html + let epoch = handler.metadata().and_then(|metadata| metadata.modified()).map_err(|_| ()) + .and_then(|systime| systime.elapsed().map_err(|_| ())) + .and_then(|elapsed| { + let secs = elapsed.as_secs(); + let nsecs = elapsed.subsec_nanos(); + let msecs = secs * 1000 + nsecs as u64 / 1000000; + Ok(msecs) + }); + + let filename = file_path.file_name(); + + match (epoch, filename) { + (Ok(epoch), Some(filename)) => Some((id, Path::new(filename).to_path_buf(), epoch)), + _ => None + } + }, + Err(_) => None + } + } + + fn read_file(&mut self, sender: IpcSender<FileManagerResult<Vec<u8>>>, id: Uuid) { + + match self.idmap.borrow().get(&id).and_then(|filepath| { + let mut buffer = vec![]; + match File::open(&filepath) { + Ok(mut handler) => { + match handler.read_to_end(&mut buffer) { + Ok(_) => Some(buffer), + Err(_) => None, + } + }, + Err(_) => None, + } + }) { + Some(buffer) => { + let _ = sender.send(Ok(buffer)); + }, + None => { + let _ = sender.send(Err(FileManagerThreadError::ReadFileError)); + } + }; + } + + fn delete_fileid(&mut self, id: Uuid) { + self.idmap.borrow_mut().remove(&id); + } +} diff --git a/components/net/lib.rs b/components/net/lib.rs index 27b9d8f4dae..22f0b50cba4 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -4,6 +4,7 @@ #![feature(box_syntax)] #![feature(fnbox)] +#![feature(fs_time)] #![feature(mpsc_select)] #![feature(plugin)] #![feature(plugin)] @@ -48,6 +49,7 @@ pub mod cookie; pub mod cookie_storage; pub mod data_loader; pub mod file_loader; +pub mod filemanager_thread; pub mod hsts; pub mod http_loader; pub mod image_cache_thread; diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index 2f0158fd020..b81abb9ce6c 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -22,3 +22,4 @@ serde = "0.7" serde_macros = "0.7" url = {version = "1.0.0", features = ["heap_size"]} websocket = "0.17" +uuid = { version = "0.2.2", features = ["v4", "serde"] } diff --git a/components/net_traits/filemanager_thread.rs b/components/net_traits/filemanager_thread.rs new file mode 100644 index 00000000000..dfc2d6a5615 --- /dev/null +++ b/components/net_traits/filemanager_thread.rs @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use ipc_channel::ipc::IpcSender; +use std::path::PathBuf; +use uuid::Uuid; + +#[derive(Deserialize, Serialize)] +pub enum FileManagerThreadMsg { + /// Select a single file, return triple (FileID, FileName, lastModified) + SelectFile(IpcSender<FileManagerResult<(Uuid, PathBuf, u64)>>), + + /// Select multiple files, return a vector of triples + SelectFiles(IpcSender<FileManagerResult<Vec<(Uuid, PathBuf, u64)>>>), + + /// Read file, return the bytes + ReadFile(IpcSender<FileManagerResult<Vec<u8>>>, Uuid), + + /// Delete the FileID entry + DeleteFileID(Uuid), +} + +pub type FileManagerResult<T> = Result<T, FileManagerThreadError>; + +#[derive(Deserialize, Serialize)] +pub enum FileManagerThreadError { + /// The selection action is invalid, nothing is selected + InvalidSelection, + /// Failure to process file information such as file name, modified time etc. + FileInfoProcessingError, + /// Failure to read the file content + ReadFileError, +} diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 33ef19ef3bd..8d67f534086 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -26,6 +26,7 @@ extern crate msg; extern crate serde; extern crate url; extern crate util; +extern crate uuid; extern crate websocket; use hyper::header::{ContentType, Headers}; @@ -42,6 +43,7 @@ use websocket::header; pub mod bluetooth_scanfilter; pub mod bluetooth_thread; +pub mod filemanager_thread; pub mod hosts; pub mod image_cache_thread; pub mod net_error_list; diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index b81cbfbdb3d..d8ce99a51c7 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1409,6 +1409,7 @@ dependencies = [ "serde_macros 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "uuid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2377,6 +2378,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 078067820e8..71eb9a39509 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -1304,6 +1304,7 @@ dependencies = [ "serde_macros 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "uuid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2242,6 +2243,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 8603fdcef09..0cb3f20e726 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -1287,6 +1287,7 @@ dependencies = [ "serde_macros 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "uuid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2223,6 +2224,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] |