diff options
-rw-r--r-- | components/net/resource_thread.rs | 25 | ||||
-rw-r--r-- | components/net/storage_thread.rs | 8 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 6 | ||||
-rw-r--r-- | components/util/Cargo.toml | 1 | ||||
-rw-r--r-- | components/util/basedir.rs | 57 | ||||
-rw-r--r-- | components/util/lib.rs | 2 | ||||
-rw-r--r-- | components/util/opts.rs | 32 | ||||
-rw-r--r-- | components/util/prefs.rs | 31 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 6 | ||||
-rw-r--r-- | ports/geckolib/Cargo.lock | 6 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 7 | ||||
-rw-r--r-- | tests/unit/util/Cargo.toml | 1 | ||||
-rw-r--r-- | tests/unit/util/prefs.rs | 32 |
13 files changed, 170 insertions, 44 deletions
diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 43919362bfa..9c6a138da32 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -211,17 +211,17 @@ impl ResourceChannelManager { let _ = sender.send(()); } CoreResourceMsg::Exit => { - if let Some(ref profile_dir) = opts::get().profile_dir { + if let Some(ref config_dir) = opts::get().config_dir { match self.resource_manager.auth_cache.read() { - Ok(auth_cache) => write_json_to_file(&*auth_cache, profile_dir, "auth_cache.json"), + Ok(auth_cache) => write_json_to_file(&*auth_cache, config_dir, "auth_cache.json"), Err(_) => warn!("Error writing auth cache to disk"), } match self.resource_manager.cookie_jar.read() { - Ok(jar) => write_json_to_file(&*jar, profile_dir, "cookie_jar.json"), + Ok(jar) => write_json_to_file(&*jar, config_dir, "cookie_jar.json"), Err(_) => warn!("Error writing cookie jar to disk"), } match self.resource_manager.hsts_list.read() { - Ok(hsts) => write_json_to_file(&*hsts, profile_dir, "hsts_list.json"), + Ok(hsts) => write_json_to_file(&*hsts, config_dir, "hsts_list.json"), Err(_) => warn!("Error writing hsts list to disk"), } } @@ -233,9 +233,9 @@ impl ResourceChannelManager { } } -pub fn read_json_from_file<T: Decodable>(data: &mut T, profile_dir: &str, filename: &str) { +pub fn read_json_from_file<T: Decodable>(data: &mut T, config_dir: &str, filename: &str) { - let path = Path::new(profile_dir).join(filename); + let path = Path::new(config_dir).join(filename); let display = path.display(); let mut file = match File::open(&path) { @@ -261,13 +261,14 @@ pub fn read_json_from_file<T: Decodable>(data: &mut T, profile_dir: &str, filena } } -pub fn write_json_to_file<T: Encodable>(data: &T, profile_dir: &str, filename: &str) { +pub fn write_json_to_file<T: Encodable>(data: &T, config_dir: &str, filename: &str) { + let json_encoded: String; match json::encode(&data) { Ok(d) => json_encoded = d, Err(_) => return, } - let path = Path::new(profile_dir).join(filename); + let path = Path::new(config_dir).join(filename); let display = path.display(); let mut file = match File::create(&path) { @@ -391,10 +392,10 @@ impl CoreResourceManager { profiler_chan: ProfilerChan) -> CoreResourceManager { let mut auth_cache = AuthCache::new(); let mut cookie_jar = CookieStorage::new(); - if let Some(ref profile_dir) = opts::get().profile_dir { - read_json_from_file(&mut auth_cache, profile_dir, "auth_cache.json"); - read_json_from_file(&mut hsts_list, profile_dir, "hsts_list.json"); - read_json_from_file(&mut cookie_jar, profile_dir, "cookie_jar.json"); + if let Some(ref config_dir) = opts::get().config_dir { + read_json_from_file(&mut auth_cache, config_dir, "auth_cache.json"); + read_json_from_file(&mut hsts_list, config_dir, "hsts_list.json"); + read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json"); } CoreResourceManager { user_agent: user_agent, diff --git a/components/net/storage_thread.rs b/components/net/storage_thread.rs index bd48993e450..1000bbf2774 100644 --- a/components/net/storage_thread.rs +++ b/components/net/storage_thread.rs @@ -38,8 +38,8 @@ struct StorageManager { impl StorageManager { fn new(port: IpcReceiver<StorageThreadMsg>) -> StorageManager { let mut local_data = HashMap::new(); - if let Some(ref profile_dir) = opts::get().profile_dir { - resource_thread::read_json_from_file(&mut local_data, profile_dir, "local_data.json"); + if let Some(ref config_dir) = opts::get().config_dir { + resource_thread::read_json_from_file(&mut local_data, config_dir, "local_data.json"); } StorageManager { port: port, @@ -75,8 +75,8 @@ impl StorageManager { self.clear(sender, url, storage_type) } StorageThreadMsg::Exit => { - if let Some(ref profile_dir) = opts::get().profile_dir { - resource_thread::write_json_to_file(&self.local_data, profile_dir, "local_data.json"); + if let Some(ref config_dir) = opts::get().config_dir { + resource_thread::write_json_to_file(&self.local_data, config_dir, "local_data.json"); } break } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 335c040e61c..5900683a181 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -2381,6 +2381,7 @@ dependencies = [ "serde_macros 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2598,6 +2599,11 @@ dependencies = [ ] [[package]] +name = "xdg" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "xi-unicode" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index a946a2739a1..c8857fcfa2e 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -30,6 +30,7 @@ serde = "0.7" serde_macros = "0.7" smallvec = "0.1" url = {version = "1.0.0", features = ["heap_size", "serde"]} +xdg = "2.0" [target.'cfg(windows)'.dependencies] kernel32-sys = "0.2" diff --git a/components/util/basedir.rs b/components/util/basedir.rs new file mode 100644 index 00000000000..3a91b5e1f66 --- /dev/null +++ b/components/util/basedir.rs @@ -0,0 +1,57 @@ +/* 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/. */ + +//! Contains routines for retrieving default config directories. +//! For linux based platforms, it uses the XDG base directory spec but provides +//! similar abstractions for non-linux platforms. + +extern crate xdg; + +use std::env; +use std::fs; +use std::path::PathBuf; + +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "windows")))] +pub fn default_config_dir() -> Option<PathBuf> { + let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); + let config_dir = xdg_dirs.get_config_home(); + Some(config_dir) +} + +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "windows")))] +pub fn default_data_dir() -> Option<PathBuf> { + let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); + let data_dir = xdg_dirs.get_data_home(); + Some(data_dir) +} + +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "windows")))] +pub fn default_cache_dir() -> Option<PathBuf> { + let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); + let cache_dir = xdg_dirs.get_cache_home(); + Some(cache_dir) +} + +#[cfg(target_os = "macos")] +pub fn default_config_dir() -> Option<PathBuf> { + let mut config_dir = env::home_dir().unwrap(); + config_dir.push("Library"); + config_dir.push("Application Support"); + config_dir.push("Servo"); + Some(config_dir) +} + +#[cfg(target_os = "windows")] +pub fn default_config_dir() -> Option<PathBuf> { + let mut config_dir = match env::var("APPDATA") { + Ok(appdata_path) => PathBuf::from(appdata_path), + Err(_) => { let mut dir = env::home_dir().unwrap(); + dir.push("Appdata"); + dir.push("Roaming"); + dir + } + }; + config_dir.push("Servo"); + Some(config_dir) +} diff --git a/components/util/lib.rs b/components/util/lib.rs index 9039e99c7b7..680e5609da0 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -38,9 +38,11 @@ extern crate rustc_serialize; extern crate serde; extern crate smallvec; extern crate url; +extern crate xdg; use std::sync::Arc; +pub mod basedir; pub mod cache; #[allow(unsafe_code)] pub mod debug_utils; diff --git a/components/util/opts.rs b/components/util/opts.rs index b882cdbbdf5..50541140b70 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -14,14 +14,14 @@ use resource_files::set_resources_path; use std::cmp; use std::default::Default; use std::env; -use std::fs; -use std::fs::File; -use std::io::{self, Read, Write}; +use std::fs::{self, File}; +use std::io::{self, Read, Write, stderr}; use std::path::{Path, PathBuf}; use std::process; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use url::{self, Url}; + /// Global flags for Servo, currently set on the command line. #[derive(Clone, Deserialize, Serialize)] pub struct Opts { @@ -197,8 +197,8 @@ pub struct Opts { /// True if WebRender should use multisample antialiasing. pub use_msaa: bool, - /// Directory path for persistent session - pub profile_dir: Option<String>, + /// Directory for a default config directory + pub config_dir: Option<String>, // Which rendering API to use. pub render_api: RenderApi, @@ -471,6 +471,7 @@ const DEFAULT_USER_AGENT: UserAgent = UserAgent::Gonk; const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; pub fn default_opts() -> Opts { + Opts { is_running_problem_test: false, url: Some(Url::parse("about:blank").unwrap()), @@ -524,7 +525,7 @@ pub fn default_opts() -> Opts { webrender_stats: false, use_msaa: false, render_api: DEFAULT_RENDER_API, - profile_dir: None, + config_dir: None, full_backtraces: false, } } @@ -581,8 +582,9 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); opts.optflag("w", "webrender", "Use webrender backend"); opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl"); - opts.optopt("", "profile-dir", - "optional directory path for user sessions", ""); + opts.optopt("", "config-dir", + "config directory following xdg spec on linux platform", ""); + let opt_match = match opts.parse(args) { Ok(m) => m, @@ -596,12 +598,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { process::exit(0); }; - if let Some(ref profile_dir) = opt_match.opt_str("profile-dir") { - if let Err(why) = fs::create_dir_all(profile_dir) { - error!("Couldn't create/open {:?}: {:?}", Path::new(profile_dir).to_string_lossy(), why); - } - } - // If this is the content process, we'll receive the real options over IPC. So just fill in // some dummy options for now. if let Some(content_process) = opt_match.opt_str("content-process") { @@ -833,7 +829,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { use_webrender: use_webrender, webrender_stats: debug_options.webrender_stats, use_msaa: debug_options.use_msaa, - profile_dir: opt_match.opt_str("profile-dir"), + config_dir: opt_match.opt_str("config-dir"), full_backtraces: debug_options.full_backtraces, }; @@ -842,9 +838,9 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { // These must happen after setting the default options, since the prefs rely on // on the resource path. // Note that command line preferences have the highest precedence - if get().profile_dir.is_some() { - prefs::add_user_prefs(); - } + + prefs::add_user_prefs(); + for pref in opt_match.opt_strs("pref").iter() { let split: Vec<&str> = pref.splitn(2, '=').collect(); let pref_name = split[0]; diff --git a/components/util/prefs.rs b/components/util/prefs.rs index 43286f2137f..3d4492dd8f7 100644 --- a/components/util/prefs.rs +++ b/components/util/prefs.rs @@ -2,6 +2,7 @@ * 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 basedir::default_config_dir; use opts; use resource_files::resources_dir_path; use rustc_serialize::json::{Json, ToJson}; @@ -166,20 +167,32 @@ pub fn extend_prefs(extension: HashMap<String, Pref>) { } pub fn add_user_prefs() { - if let Some(ref dir) = opts::get().profile_dir { - let mut path = PathBuf::from(dir); - path.push("prefs.json"); - if let Ok(file) = File::open(path) { - if let Ok(prefs) = read_prefs_from_file(file) { - extend_prefs(prefs); + match opts::get().config_dir { + Some(ref config_path) => { + let mut path = PathBuf::from(config_path); + init_user_prefs(&mut path); + } + None => { + let mut path = default_config_dir().unwrap(); + if path.join("prefs.json").exists() { + init_user_prefs(&mut path); } - } else { - writeln!(&mut stderr(), "Error opening prefs.json from profile_dir") - .expect("failed printing to stderr"); } } } +fn init_user_prefs(path: &mut PathBuf) { + path.push("prefs.json"); + if let Ok(file) = File::open(path) { + if let Ok(prefs) = read_prefs_from_file(file) { + extend_prefs(prefs); + } + } else { + writeln!(&mut stderr(), "Error opening prefs.json from config directory") + .expect("failed printing to stderr"); + } +} + fn read_prefs() -> Result<HashMap<String, Pref>, ()> { let mut path = resources_dir_path(); path.push("prefs.json"); diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 5f86dec09d8..ac87931b1d0 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -2249,6 +2249,7 @@ dependencies = [ "serde_macros 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2459,6 +2460,11 @@ dependencies = [ ] [[package]] +name = "xdg" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "xi-unicode" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock index 08bab05fb1e..c444a9dd93c 100644 --- a/ports/geckolib/Cargo.lock +++ b/ports/geckolib/Cargo.lock @@ -584,6 +584,7 @@ dependencies = [ "serde_macros 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -618,3 +619,8 @@ name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "xdg" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 008d8c9cb24..37e4267a41c 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -2234,8 +2234,8 @@ dependencies = [ "serde 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2415,6 +2415,11 @@ dependencies = [ ] [[package]] +name = "xdg" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "xi-unicode" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/tests/unit/util/Cargo.toml b/tests/unit/util/Cargo.toml index c61afbb1ea0..6a7bfa244b8 100644 --- a/tests/unit/util/Cargo.toml +++ b/tests/unit/util/Cargo.toml @@ -10,3 +10,4 @@ doctest = false [dependencies] util = {path = "../../../components/util"} + diff --git a/tests/unit/util/prefs.rs b/tests/unit/util/prefs.rs index d6c5b5b98bd..20ad1cdbca1 100644 --- a/tests/unit/util/prefs.rs +++ b/tests/unit/util/prefs.rs @@ -2,6 +2,9 @@ * 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 std::fs::{self, File}; +use std::io::{Read, Write}; +use util::basedir; use util::prefs::{PrefValue, extend_prefs, read_prefs_from_file, get_pref, set_pref, reset_pref}; #[test] @@ -42,3 +45,32 @@ fn test_get_set_reset_extend() { assert_eq!(*get_pref("layout.writing-mode.enabled"), PrefValue::Boolean(true)); assert_eq!(*get_pref("extra.stuff"), PrefValue::Boolean(false)); } + +#[test] +fn test_default_config_dir_create_read_write() { + + let json_str = "{\ + \"layout.writing-mode.enabled\": true,\ + \"extra.stuff\": false,\ + \"shell.homepage\": \"https://google.com\"\ +}"; + let mut expected_json = String::new(); + let config_path = basedir::default_config_dir().unwrap(); + + if !config_path.exists() { + fs::create_dir_all(&config_path).unwrap(); + } + + let json_path = config_path.join("test_config.json"); + + let mut fd = File::create(&json_path).unwrap(); + assert_eq!(json_path.exists(), true); + + fd.write_all(json_str.as_bytes()).unwrap(); + let mut fd = File::open(&json_path).unwrap(); + fd.read_to_string(&mut expected_json).unwrap(); + + assert_eq!(json_str, expected_json); + + fs::remove_file(&json_path).unwrap(); +} |