aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhen Zhang <izgzhen@gmail.com>2016-05-03 08:47:27 +0800
committerZhen Zhang <izgzhen@gmail.com>2016-05-11 15:14:03 +0800
commitc618ee21d0cca19631ebab9a1d735c48a0a7679a (patch)
tree4d4c8be52f78509cd4cf1a2f5f7ff1f30c1226c7
parentab12d8098fcc0517b64643d25683e2e15e665410 (diff)
downloadservo-c618ee21d0cca19631ebab9a1d735c48a0a7679a.tar.gz
servo-c618ee21d0cca19631ebab9a1d735c48a0a7679a.zip
add filemanager_thread
-rw-r--r--components/net/filemanager_thread.rs137
-rw-r--r--components/net/lib.rs2
-rw-r--r--components/net_traits/Cargo.toml1
-rw-r--r--components/net_traits/filemanager_thread.rs34
-rw-r--r--components/net_traits/lib.rs2
-rw-r--r--components/servo/Cargo.lock2
-rw-r--r--ports/cef/Cargo.lock2
-rw-r--r--ports/gonk/Cargo.lock2
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]]