delegate resource reading to embedder

This commit is contained in:
Paul Rouget 2018-04-11 16:04:07 +08:00
parent 21517504cb
commit 9fb5795f37
52 changed files with 472 additions and 396 deletions

View file

@ -13,6 +13,7 @@ doctest = false
[dependencies]
euclid = "0.17"
embedder_traits = { path = "../embedder_traits" }
getopts = "0.2.11"
lazy_static = "1"
log = "0.4"

View file

@ -6,6 +6,7 @@
#[cfg(target_os = "android")]
extern crate android_injected_glue;
extern crate embedder_traits;
extern crate euclid;
extern crate getopts;
#[macro_use] extern crate lazy_static;
@ -22,7 +23,6 @@ extern crate xdg;
pub mod basedir;
#[allow(unsafe_code)] pub mod opts;
pub mod prefs;
pub mod resource_files;
pub fn servo_version() -> String {
let cargo_version = env!("CARGO_PKG_VERSION");

View file

@ -9,7 +9,6 @@ use euclid::TypedSize2D;
use getopts::Options;
use num_cpus;
use prefs::{self, PrefValue, PREFS};
use resource_files::set_resources_path;
use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use std::borrow::Cow;
@ -196,6 +195,9 @@ pub struct Opts {
/// True if webrender is allowed to batch draw calls as instances.
pub webrender_batch: bool,
/// Load shaders from disk.
pub shaders_dir: Option<PathBuf>,
/// True to compile all webrender shaders at init time. This is mostly
/// useful when modifying the shaders, to ensure they all compile
/// after each change is made.
@ -544,6 +546,7 @@ pub fn default_opts() -> Opts {
is_printing_version: false,
webrender_record: false,
webrender_batch: true,
shaders_dir: None,
precache_shaders: false,
signpost: false,
certificate_path: None,
@ -575,6 +578,8 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
"Uses userscripts in resources/user-agent-js, or a specified full path", "");
opts.optmulti("", "user-stylesheet",
"A user stylesheet to be added to every document", "file.css");
opts.optopt("", "shaders",
"Shaders will be loaded from the specified directory instead of using the builtin ones.", "");
opts.optflag("z", "headless", "Headless mode");
opts.optflag("f", "hard-fail", "Exit on thread failure instead of displaying about:failure");
opts.optflag("F", "soft-fail", "Display about:failure on thread failure instead of exiting");
@ -619,8 +624,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
Err(f) => args_fail(&f.to_string()),
};
set_resources_path(opt_match.opt_str("resources-path"));
if opt_match.opt_present("h") || opt_match.opt_present("help") {
print_usage(app_name, &opts);
process::exit(0);
@ -844,6 +847,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
is_printing_version: is_printing_version,
webrender_record: debug_options.webrender_record,
webrender_batch: !debug_options.webrender_disable_batch,
shaders_dir: opt_match.opt_str("shaders").map(Into::into),
precache_shaders: debug_options.precache_shaders,
signpost: debug_options.signpost,
certificate_path: opt_match.opt_str("certificate-path"),

View file

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use basedir::default_config_dir;
use embedder_traits::resources::{self, Resource};
use num_cpus;
use opts;
use resource_files::resources_dir_path;
use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned;
use std::cmp::max;
@ -18,7 +18,7 @@ use std::sync::{Arc, RwLock};
lazy_static! {
pub static ref PREFS: Preferences = {
let defaults = default_prefs();
if let Ok(prefs) = read_prefs() {
if let Ok(prefs) = read_prefs(&resources::read_string(Resource::Preferences)) {
defaults.extend(prefs);
}
defaults
@ -156,9 +156,8 @@ pub fn default_prefs() -> Preferences {
prefs
}
pub fn read_prefs_from_file<T>(mut file: T)
-> Result<HashMap<String, Pref>, ()> where T: Read {
let json = Json::from_reader(&mut file).or_else(|e| {
pub fn read_prefs(txt: &str) -> Result<HashMap<String, Pref>, ()> {
let json = Json::from_str(txt).or_else(|e| {
println!("Ignoring invalid JSON in preferences: {:?}.", e);
Err(())
})?;
@ -194,8 +193,10 @@ pub fn add_user_prefs() {
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) {
if let Ok(mut file) = File::open(path) {
let mut txt = String::new();
file.read_to_string(&mut txt).expect("Can't read use prefs");
if let Ok(prefs) = read_prefs(&txt) {
PREFS.extend(prefs);
}
} else {
@ -204,19 +205,6 @@ fn init_user_prefs(path: &mut PathBuf) {
}
}
fn read_prefs() -> Result<HashMap<String, Pref>, ()> {
let mut path = resources_dir_path().map_err(|_| ())?;
path.push("prefs.json");
let file = File::open(path).or_else(|e| {
writeln!(&mut stderr(), "Error opening preferences: {:?}.", e)
.expect("failed printing to stderr");
Err(())
})?;
read_prefs_from_file(file)
}
pub struct Preferences(Arc<RwLock<HashMap<String, Pref>>>);
impl Preferences {

View file

@ -1,83 +0,0 @@
/* 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/. */
#[cfg(target_os = "android")]
use android_injected_glue;
#[cfg(not(target_os = "android"))]
use std::env;
#[cfg(target_os = "android")]
use std::ffi::CStr;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
lazy_static! {
static ref CMD_RESOURCE_DIR: Arc<Mutex<Option<String>>> = {
Arc::new(Mutex::new(None))
};
}
pub fn set_resources_path(path: Option<String>) {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
*dir = path;
}
#[cfg(target_os = "android")]
#[allow(unsafe_code)]
pub fn resources_dir_path() -> io::Result<PathBuf> {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
if let Some(ref path) = *dir {
return Ok(PathBuf::from(path));
}
let data_path = unsafe {
CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
};
let path = PathBuf::from(data_path.to_str().unwrap());
*dir = Some(path.to_str().unwrap().to_owned());
Ok(path)
}
#[cfg(not(target_os = "android"))]
pub fn resources_dir_path() -> io::Result<PathBuf> {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
if let Some(ref path) = *dir {
return Ok(PathBuf::from(path));
}
// FIXME: Find a way to not rely on the executable being
// under `<servo source>[/$target_triple]/target/debug`
// or `<servo source>[/$target_triple]/target/release`.
let mut path = env::current_exe()?;
// Follow symlink
path = path.canonicalize()?;
while path.pop() {
path.push("resources");
if path.is_dir() {
break;
}
path.pop();
// Check for Resources on mac when using a case sensitive filesystem.
path.push("Resources");
if path.is_dir() {
break;
}
path.pop();
}
*dir = Some(path.to_str().unwrap().to_owned());
Ok(path)
}
pub fn read_resource_file<P: AsRef<Path>>(relative_path: P) -> io::Result<Vec<u8>> {
let mut path = resources_dir_path()?;
path.push(relative_path);
let mut file = File::open(&path)?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
Ok(data)
}

View file

@ -2,8 +2,10 @@
* 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/. */
extern crate embedder_traits;
extern crate servo_config;
use embedder_traits::resources::register_resources_for_tests;
use servo_config::opts::{parse_url_or_filename, parse_pref_from_command_line};
use servo_config::prefs::{PrefValue, PREFS};
use std::path::Path;
@ -73,6 +75,7 @@ fn test_argument_parsing_special() {
#[test]
fn test_parse_pref_from_command_line() {
register_resources_for_tests();
// Test with boolean values.
parse_pref_from_command_line("testtrue=true");
assert_eq!(*PREFS.get("testtrue"), PrefValue::Boolean(true));

View file

@ -2,10 +2,12 @@
* 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/. */
extern crate embedder_traits;
extern crate servo_config;
use embedder_traits::resources::register_resources_for_tests;
use servo_config::basedir;
use servo_config::prefs::{PREFS, PrefValue, read_prefs_from_file};
use servo_config::prefs::{PREFS, PrefValue, read_prefs};
use std::fs::{self, File};
use std::io::{Read, Write};
@ -17,7 +19,7 @@ fn test_create_pref() {
\"shell.homepage\": \"https://servo.org\"\
}";
let prefs = read_prefs_from_file(json_str.as_bytes());
let prefs = read_prefs(json_str);
assert!(prefs.is_ok());
let prefs = prefs.unwrap();
@ -26,6 +28,7 @@ fn test_create_pref() {
#[test]
fn test_get_set_reset_extend() {
register_resources_for_tests();
let json_str = "{\
\"layout.writing-mode.enabled\": true,\
\"extra.stuff\": false,\
@ -41,7 +44,7 @@ fn test_get_set_reset_extend() {
PREFS.reset("shell.homepage");
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://servo.org".to_owned()));
let extension = read_prefs_from_file(json_str.as_bytes()).unwrap();
let extension = read_prefs(json_str).unwrap();
PREFS.extend(extension);
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://google.com".to_owned()));
assert_eq!(*PREFS.get("layout.writing-mode.enabled"), PrefValue::Boolean(true));