aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/net/resource_thread.rs25
-rw-r--r--components/net/storage_thread.rs8
-rw-r--r--components/servo/Cargo.lock6
-rw-r--r--components/util/Cargo.toml1
-rw-r--r--components/util/basedir.rs57
-rw-r--r--components/util/lib.rs2
-rw-r--r--components/util/opts.rs32
-rw-r--r--components/util/prefs.rs31
-rw-r--r--ports/cef/Cargo.lock6
-rw-r--r--ports/geckolib/Cargo.lock6
-rw-r--r--ports/gonk/Cargo.lock7
-rw-r--r--tests/unit/util/Cargo.toml1
-rw-r--r--tests/unit/util/prefs.rs32
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();
+}