Auto merge of #20533 - paulrouget:res, r=mbrubeck

Delegate resource reading to embedder

Now the embedder provides the content of the files itself. Now, on Android, we can use regular assets instead of unzipping all the resources on the scared at startup.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [ ] `./mach build-geckolib` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #15635 (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20533)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-04-27 13:50:18 -04:00 committed by GitHub
commit d1378d6bad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 472 additions and 396 deletions

18
Cargo.lock generated
View file

@ -193,10 +193,10 @@ dependencies = [
name = "bluetooth_traits" name = "bluetooth_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"embedder_traits 0.0.1",
"ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
] ]
[[package]] [[package]]
@ -452,6 +452,7 @@ dependencies = [
"compositing 0.0.1", "compositing 0.0.1",
"debugger 0.0.1", "debugger 0.0.1",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"embedder_traits 0.0.1",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/servo/gaol)", "gaol 0.0.1 (git+https://github.com/servo/gaol)",
"gfx 0.0.1", "gfx 0.0.1",
@ -782,6 +783,13 @@ name = "either"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "embedder_traits"
version = "0.0.1"
dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.7.1" version = "0.7.1"
@ -1453,6 +1461,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"embedder_traits 0.0.1",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx 0.0.1", "gfx 0.0.1",
@ -1563,6 +1572,7 @@ dependencies = [
"debugger 0.0.1", "debugger 0.0.1",
"devtools 0.0.1", "devtools 0.0.1",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"embedder_traits 0.0.1",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gaol 0.0.1 (git+https://github.com/servo/gaol)", "gaol 0.0.1 (git+https://github.com/servo/gaol)",
@ -1882,6 +1892,7 @@ dependencies = [
"brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"embedder_traits 0.0.1",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1932,6 +1943,7 @@ name = "net_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"embedder_traits 0.0.1",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2510,6 +2522,7 @@ dependencies = [
"devtools_traits 0.0.1", "devtools_traits 0.0.1",
"dom_struct 0.0.1", "dom_struct 0.0.1",
"domobject_derive 0.0.1", "domobject_derive 0.0.1",
"embedder_traits 0.0.1",
"encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2736,6 +2749,7 @@ dependencies = [
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.34 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.4.34 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libservo 0.0.1", "libservo 0.0.1",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)", "osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
@ -2852,6 +2866,7 @@ name = "servo_config"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"embedder_traits 0.0.1",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3078,6 +3093,7 @@ dependencies = [
"app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"embedder_traits 0.0.1",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -13,4 +13,4 @@ path = "lib.rs"
ipc-channel = "0.10" ipc-channel = "0.10"
regex = "0.2" regex = "0.2"
serde = "1.0" serde = "1.0"
servo_config = {path = "../config"} embedder_traits = { path = "../embedder_traits" }

View file

@ -2,15 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use regex::Regex; use regex::Regex;
use servo_config::resource_files::read_resource_file;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::BufRead;
use std::string::String; use std::string::String;
const BLOCKLIST_FILE: &'static str = "gatt_blocklist.txt";
const BLOCKLIST_FILE_NOT_FOUND: &'static str = "Could not find gatt_blocklist.txt file";
const EXCLUDE_READS: &'static str = "exclude-reads"; const EXCLUDE_READS: &'static str = "exclude-reads";
const EXCLUDE_WRITES: &'static str = "exclude-writes"; const EXCLUDE_WRITES: &'static str = "exclude-writes";
const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
@ -75,15 +72,11 @@ impl BluetoothBlocklist {
fn parse_blocklist() -> Option<HashMap<String, Blocklist>> { fn parse_blocklist() -> Option<HashMap<String, Blocklist>> {
// Step 1 missing, currently we parse ./resources/gatt_blocklist.txt. // Step 1 missing, currently we parse ./resources/gatt_blocklist.txt.
let valid_uuid_regex = Regex::new(VALID_UUID_REGEX).unwrap(); let valid_uuid_regex = Regex::new(VALID_UUID_REGEX).unwrap();
let content = read_resource_file(BLOCKLIST_FILE).expect(BLOCKLIST_FILE_NOT_FOUND); let content = resources::read_string(Resource::BluetoothBlocklist);
// Step 3 // Step 3
let mut result = HashMap::new(); let mut result = HashMap::new();
// Step 2 and 4 // Step 2 and 4
for line in content.lines() { for line in content.lines() {
let line = match line {
Ok(l) => l,
Err(_) => return None,
};
// Step 4.1 // Step 4.1
if line.is_empty() || line.starts_with('#') { if line.is_empty() || line.starts_with('#') {
continue; continue;

View file

@ -2,10 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate ipc_channel; extern crate ipc_channel;
extern crate regex; extern crate regex;
#[macro_use] extern crate serde; #[macro_use] extern crate serde;
extern crate servo_config;
pub mod blocklist; pub mod blocklist;
pub mod scanfilter; pub mod scanfilter;

View file

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

View file

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

View file

@ -9,7 +9,6 @@ use euclid::TypedSize2D;
use getopts::Options; use getopts::Options;
use num_cpus; use num_cpus;
use prefs::{self, PrefValue, PREFS}; use prefs::{self, PrefValue, PREFS};
use resource_files::set_resources_path;
use servo_geometry::DeviceIndependentPixel; use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::Cow; use std::borrow::Cow;
@ -196,6 +195,9 @@ pub struct Opts {
/// True if webrender is allowed to batch draw calls as instances. /// True if webrender is allowed to batch draw calls as instances.
pub webrender_batch: bool, 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 /// True to compile all webrender shaders at init time. This is mostly
/// useful when modifying the shaders, to ensure they all compile /// useful when modifying the shaders, to ensure they all compile
/// after each change is made. /// after each change is made.
@ -544,6 +546,7 @@ pub fn default_opts() -> Opts {
is_printing_version: false, is_printing_version: false,
webrender_record: false, webrender_record: false,
webrender_batch: true, webrender_batch: true,
shaders_dir: None,
precache_shaders: false, precache_shaders: false,
signpost: false, signpost: false,
certificate_path: None, 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", ""); "Uses userscripts in resources/user-agent-js, or a specified full path", "");
opts.optmulti("", "user-stylesheet", opts.optmulti("", "user-stylesheet",
"A user stylesheet to be added to every document", "file.css"); "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("z", "headless", "Headless mode");
opts.optflag("f", "hard-fail", "Exit on thread failure instead of displaying about:failure"); 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"); 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()), 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") { if opt_match.opt_present("h") || opt_match.opt_present("help") {
print_usage(app_name, &opts); print_usage(app_name, &opts);
process::exit(0); process::exit(0);
@ -844,6 +847,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
is_printing_version: is_printing_version, is_printing_version: is_printing_version,
webrender_record: debug_options.webrender_record, webrender_record: debug_options.webrender_record,
webrender_batch: !debug_options.webrender_disable_batch, webrender_batch: !debug_options.webrender_disable_batch,
shaders_dir: opt_match.opt_str("shaders").map(Into::into),
precache_shaders: debug_options.precache_shaders, precache_shaders: debug_options.precache_shaders,
signpost: debug_options.signpost, signpost: debug_options.signpost,
certificate_path: opt_match.opt_str("certificate-path"), 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use basedir::default_config_dir; use basedir::default_config_dir;
use embedder_traits::resources::{self, Resource};
use num_cpus; use num_cpus;
use opts; use opts;
use resource_files::resources_dir_path;
use rustc_serialize::json::{Json, ToJson}; use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cmp::max; use std::cmp::max;
@ -18,7 +18,7 @@ use std::sync::{Arc, RwLock};
lazy_static! { lazy_static! {
pub static ref PREFS: Preferences = { pub static ref PREFS: Preferences = {
let defaults = default_prefs(); 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.extend(prefs);
} }
defaults defaults
@ -156,9 +156,8 @@ pub fn default_prefs() -> Preferences {
prefs prefs
} }
pub fn read_prefs_from_file<T>(mut file: T) pub fn read_prefs(txt: &str) -> Result<HashMap<String, Pref>, ()> {
-> Result<HashMap<String, Pref>, ()> where T: Read { let json = Json::from_str(txt).or_else(|e| {
let json = Json::from_reader(&mut file).or_else(|e| {
println!("Ignoring invalid JSON in preferences: {:?}.", e); println!("Ignoring invalid JSON in preferences: {:?}.", e);
Err(()) Err(())
})?; })?;
@ -194,8 +193,10 @@ pub fn add_user_prefs() {
fn init_user_prefs(path: &mut PathBuf) { fn init_user_prefs(path: &mut PathBuf) {
path.push("prefs.json"); path.push("prefs.json");
if let Ok(file) = File::open(path) { if let Ok(mut file) = File::open(path) {
if let Ok(prefs) = read_prefs_from_file(file) { 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); PREFS.extend(prefs);
} }
} else { } 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>>>); pub struct Preferences(Arc<RwLock<HashMap<String, Pref>>>);
impl Preferences { 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate servo_config; 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::opts::{parse_url_or_filename, parse_pref_from_command_line};
use servo_config::prefs::{PrefValue, PREFS}; use servo_config::prefs::{PrefValue, PREFS};
use std::path::Path; use std::path::Path;
@ -73,6 +75,7 @@ fn test_argument_parsing_special() {
#[test] #[test]
fn test_parse_pref_from_command_line() { fn test_parse_pref_from_command_line() {
register_resources_for_tests();
// Test with boolean values. // Test with boolean values.
parse_pref_from_command_line("testtrue=true"); parse_pref_from_command_line("testtrue=true");
assert_eq!(*PREFS.get("testtrue"), PrefValue::Boolean(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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate servo_config; extern crate servo_config;
use embedder_traits::resources::register_resources_for_tests;
use servo_config::basedir; 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::fs::{self, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
@ -17,7 +19,7 @@ fn test_create_pref() {
\"shell.homepage\": \"https://servo.org\"\ \"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()); assert!(prefs.is_ok());
let prefs = prefs.unwrap(); let prefs = prefs.unwrap();
@ -26,6 +28,7 @@ fn test_create_pref() {
#[test] #[test]
fn test_get_set_reset_extend() { fn test_get_set_reset_extend() {
register_resources_for_tests();
let json_str = "{\ let json_str = "{\
\"layout.writing-mode.enabled\": true,\ \"layout.writing-mode.enabled\": true,\
\"extra.stuff\": false,\ \"extra.stuff\": false,\
@ -41,7 +44,7 @@ fn test_get_set_reset_extend() {
PREFS.reset("shell.homepage"); PREFS.reset("shell.homepage");
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://servo.org".to_owned())); 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); PREFS.extend(extension);
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://google.com".to_owned())); assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://google.com".to_owned()));
assert_eq!(*PREFS.get("layout.writing-mode.enabled"), PrefValue::Boolean(true)); assert_eq!(*PREFS.get("layout.writing-mode.enabled"), PrefValue::Boolean(true));

View file

@ -19,6 +19,7 @@ compositing = {path = "../compositing"}
debugger = {path = "../debugger"} debugger = {path = "../debugger"}
devtools_traits = {path = "../devtools_traits"} devtools_traits = {path = "../devtools_traits"}
euclid = "0.17" euclid = "0.17"
embedder_traits = { path = "../embedder_traits" }
gfx = {path = "../gfx"} gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"} gfx_traits = {path = "../gfx_traits"}
hyper = "0.10" hyper = "0.10"

View file

@ -14,6 +14,8 @@ extern crate clipboard;
extern crate compositing; extern crate compositing;
extern crate debugger; extern crate debugger;
extern crate devtools_traits; extern crate devtools_traits;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
extern crate embedder_traits;
extern crate euclid; extern crate euclid;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
extern crate gaol; extern crate gaol;

View file

@ -2,18 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources;
use gaol::profile::{Operation, PathPattern, Profile}; use gaol::profile::{Operation, PathPattern, Profile};
use servo_config::resource_files;
use std::path::PathBuf; use std::path::PathBuf;
/// Our content process sandbox profile on Mac. As restrictive as possible. /// Our content process sandbox profile on Mac. As restrictive as possible.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn content_process_sandbox_profile() -> Profile { pub fn content_process_sandbox_profile() -> Profile {
use gaol::platform; use gaol::platform;
Profile::new(vec![
let mut operations = vec![
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))), Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))),
Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path()
.expect("Cannot find resource dir"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/Library/Fonts"))), Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/Library/Fonts"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/System/Library/Fonts"))), Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/System/Library/Fonts"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from( Operation::FileReadAll(PathPattern::Subpath(PathBuf::from(
@ -27,16 +26,32 @@ pub fn content_process_sandbox_profile() -> Profile {
Operation::SystemInfoRead, Operation::SystemInfoRead,
Operation::PlatformSpecific(platform::macos::Operation::MachLookup( Operation::PlatformSpecific(platform::macos::Operation::MachLookup(
b"com.apple.FontServer".to_vec())), b"com.apple.FontServer".to_vec())),
]).expect("Failed to create sandbox profile!") ];
operations.extend(resources::sandbox_access_files().into_iter().map(|p| {
Operation::FileReadAll(PathPattern::Literal(p))
}));
operations.extend(resources::sandbox_access_files_dirs().into_iter().map(|p| {
Operation::FileReadAll(PathPattern::Subpath(p))
}));
Profile::new(operations).expect("Failed to create sandbox profile!")
} }
/// Our content process sandbox profile on Linux. As restrictive as possible. /// Our content process sandbox profile on Linux. As restrictive as possible.
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
pub fn content_process_sandbox_profile() -> Profile { pub fn content_process_sandbox_profile() -> Profile {
Profile::new(vec![ let mut operations = vec![
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))), Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))),
Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path() ];
.expect("Cannot find resource dir"))),
]).expect("Failed to create sandbox profile!") operations.extend(resources::sandbox_access_files().into_iter().map(|p| {
Operation::FileReadAll(PathPattern::Literal(p))
}));
operations.extend(resources::sandbox_access_files_dirs().into_iter().map(|p| {
Operation::FileReadAll(PathPattern::Subpath(p))
}));
Profile::new(operations).expect("Failed to create sandbox profile!")
} }

View file

@ -0,0 +1,13 @@
[package]
name = "embedder_traits"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
publish = false
[lib]
name = "embedder_traits"
path = "lib.rs"
[dependencies]
lazy_static = "1"

View file

@ -0,0 +1,7 @@
/* 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/. */
#[macro_use] extern crate lazy_static;
pub mod resources;

View file

@ -0,0 +1,97 @@
/* 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 std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::{Once, ONCE_INIT, RwLock};
lazy_static! {
static ref RES: RwLock<Option<Box<ResourceReaderMethods + Sync + Send>>> = RwLock::new(None);
}
pub fn set(reader: Box<ResourceReaderMethods + Sync + Send>) {
*RES.write().unwrap() = Some(reader);
}
pub fn read_bytes(res: Resource) -> Vec<u8> {
RES.read().unwrap().as_ref().expect("Resource reader not set.").read(res)
}
pub fn read_string(res: Resource) -> String {
String::from_utf8(read_bytes(res)).unwrap()
}
pub fn sandbox_access_files() -> Vec<PathBuf> {
RES.read().unwrap().as_ref().expect("Resource reader not set.").sandbox_access_files()
}
pub fn sandbox_access_files_dirs() -> Vec<PathBuf> {
RES.read().unwrap().as_ref().expect("Resource reader not set.").sandbox_access_files_dirs()
}
pub enum Resource {
Preferences,
BluetoothBlocklist,
DomainList,
HstsPreloadList,
SSLCertificates,
BadCertHTML,
NetErrorHTML,
UserAgentCSS,
ServoCSS,
PresentationalHintsCSS,
QuirksModeCSS,
RippyPNG,
}
pub trait ResourceReaderMethods {
fn read(&self, res: Resource) -> Vec<u8>;
fn sandbox_access_files(&self) -> Vec<PathBuf>;
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf>;
}
static INIT: Once = ONCE_INIT;
pub fn register_resources_for_tests() {
INIT.call_once(|| {
struct ResourceReader;
impl ResourceReaderMethods for ResourceReader {
fn sandbox_access_files(&self) -> Vec<PathBuf> { vec![] }
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> { vec![] }
fn read(&self, file: Resource) -> Vec<u8> {
let file = match file {
Resource::Preferences => "prefs.json",
Resource::BluetoothBlocklist => "gatt_blocklist.txt",
Resource::DomainList => "public_domains.txt",
Resource::HstsPreloadList => "hsts_preload.json",
Resource::SSLCertificates => "certs",
Resource::BadCertHTML => "badcert.html",
Resource::NetErrorHTML => "neterror.html",
Resource::UserAgentCSS => "user-agent.css",
Resource::ServoCSS => "servo.css",
Resource::PresentationalHintsCSS => "presentational-hints.css",
Resource::QuirksModeCSS => "quirks-mode.css",
Resource::RippyPNG => "rippy.png",
};
let mut path = env::current_exe().unwrap();
path = path.canonicalize().unwrap();
while path.pop() {
path.push("resources");
if path.is_dir() {
break;
}
path.pop();
}
path.push(file);
let mut buffer = vec![];
File::open(path).expect(&format!("Can't find file: {}", file))
.read_to_end(&mut buffer).expect("Can't read file");
buffer
}
}
set(Box::new(ResourceReader));
});
}

View file

@ -15,6 +15,7 @@ unstable = ["parking_lot/nightly"]
[dependencies] [dependencies]
app_units = "0.6" app_units = "0.6"
atomic_refcell = "0.1" atomic_refcell = "0.1"
embedder_traits = {path = "../embedder_traits"}
euclid = "0.17" euclid = "0.17"
fnv = "1.0" fnv = "1.0"
gfx = {path = "../gfx"} gfx = {path = "../gfx"}

View file

@ -9,6 +9,7 @@
extern crate app_units; extern crate app_units;
extern crate atomic_refcell; extern crate atomic_refcell;
extern crate embedder_traits;
extern crate euclid; extern crate euclid;
extern crate fnv; extern crate fnv;
extern crate gfx; extern crate gfx;
@ -55,6 +56,7 @@ mod dom_wrapper;
use app_units::Au; use app_units::Au;
use dom_wrapper::{ServoLayoutElement, ServoLayoutDocument, ServoLayoutNode}; use dom_wrapper::{ServoLayoutElement, ServoLayoutDocument, ServoLayoutNode};
use dom_wrapper::drop_style_and_layout_data; use dom_wrapper::drop_style_and_layout_data;
use embedder_traits::resources::{self, Resource};
use euclid::{Point2D, Rect, Size2D, TypedScale, TypedSize2D}; use euclid::{Point2D, Rect, Size2D, TypedScale, TypedSize2D};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use gfx::display_list::{OpaqueNode, WebRenderImageInfo}; use gfx::display_list::{OpaqueNode, WebRenderImageInfo};
@ -110,7 +112,6 @@ use servo_arc::Arc as ServoArc;
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_config::opts; use servo_config::opts;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_config::resource_files::read_resource_file;
use servo_geometry::MaxRect; use servo_geometry::MaxRect;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -1740,11 +1741,11 @@ fn get_root_flow_background_color(flow: &mut Flow) -> webrender_api::ColorF {
fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> { fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
fn parse_ua_stylesheet( fn parse_ua_stylesheet(
shared_lock: &SharedRwLock, shared_lock: &SharedRwLock,
filename: &'static str, filename: &str,
content: &[u8],
) -> Result<DocumentStyleSheet, &'static str> { ) -> Result<DocumentStyleSheet, &'static str> {
let res = read_resource_file(filename).map_err(|_| filename)?;
Ok(DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes( Ok(DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes(
&res, content,
ServoUrl::parse(&format!("chrome://resources/{:?}", filename)).unwrap(), ServoUrl::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
None, None,
None, None,
@ -1758,12 +1759,17 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
} }
let shared_lock = SharedRwLock::new(); let shared_lock = SharedRwLock::new();
let mut user_or_user_agent_stylesheets = vec!();
// FIXME: presentational-hints.css should be at author origin with zero specificity. // FIXME: presentational-hints.css should be at author origin with zero specificity.
// (Does it make a difference?) // (Does it make a difference?)
for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] { let mut user_or_user_agent_stylesheets = vec![
user_or_user_agent_stylesheets.push(parse_ua_stylesheet(&shared_lock, filename)?); parse_ua_stylesheet(&shared_lock, "user-agent.css",
} &resources::read_bytes(Resource::UserAgentCSS))?,
parse_ua_stylesheet(&shared_lock, "servo.css",
&resources::read_bytes(Resource::ServoCSS))?,
parse_ua_stylesheet(&shared_lock, "presentational-hints.css",
&resources::read_bytes(Resource::PresentationalHintsCSS))?,
];
for &(ref contents, ref url) in &opts::get().user_stylesheets { for &(ref contents, ref url) in &opts::get().user_stylesheets {
user_or_user_agent_stylesheets.push( user_or_user_agent_stylesheets.push(
DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes( DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes(
@ -1781,7 +1787,8 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
); );
} }
let quirks_mode_stylesheet = parse_ua_stylesheet(&shared_lock, "quirks-mode.css")?; let quirks_mode_stylesheet = parse_ua_stylesheet(&shared_lock, "quirks-mode.css",
&resources::read_bytes(Resource::QuirksModeCSS))?;
Ok(UserAgentStylesheets { Ok(UserAgentStylesheets {
shared_lock: shared_lock, shared_lock: shared_lock,

View file

@ -16,6 +16,7 @@ base64 = "0.6"
brotli = "1.0.6" brotli = "1.0.6"
cookie = "0.10" cookie = "0.10"
devtools_traits = {path = "../devtools_traits"} devtools_traits = {path = "../devtools_traits"}
embedder_traits = { path = "../embedder_traits" }
flate2 = "1" flate2 = "1"
hyper = "0.10" hyper = "0.10"
hyper_serde = "0.8" hyper_serde = "0.8"

View file

@ -1,31 +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/. */
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl;
use std::fs::canonicalize;
use url::percent_encoding::percent_decode;
pub fn resolve_chrome_url(url: &ServoUrl) -> Result<ServoUrl, ()> {
assert_eq!(url.scheme(), "chrome");
if url.host_str() != Some("resources") {
return Err(())
}
let resources = canonicalize(resources_dir_path().expect("Error finding resource folder"))
.expect("Error canonicalizing path to the resources directory");
let mut path = resources.clone();
for segment in url.path_segments().unwrap() {
match percent_decode(segment.as_bytes()).decode_utf8() {
// Check ".." to prevent access to files outside of the resources directory.
Ok(segment) => path.push(&*segment),
_ => return Err(())
}
}
match canonicalize(path) {
Ok(ref path) if path.starts_with(&resources) && path.exists() => {
Ok(ServoUrl::from_file_path(path).unwrap())
}
_ => Err(())
}
}

View file

@ -9,9 +9,9 @@ use hyper::net::{NetworkConnector, HttpsStream, HttpStream, SslClient};
use hyper_openssl::OpensslClient; use hyper_openssl::OpensslClient;
use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3}; use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3};
use openssl::ssl::{SslConnectorBuilder, SslMethod}; use openssl::ssl::{SslConnectorBuilder, SslMethod};
use openssl::x509;
use std::io; use std::io;
use std::net::TcpStream; use std::net::TcpStream;
use std::path::PathBuf;
pub struct HttpsConnector { pub struct HttpsConnector {
ssl: OpensslClient, ssl: OpensslClient,
@ -50,9 +50,33 @@ impl NetworkConnector for HttpsConnector {
pub type Connector = HttpsConnector; pub type Connector = HttpsConnector;
pub fn create_ssl_client(ca_file: &PathBuf) -> OpensslClient { pub fn create_ssl_client(certs: &str) -> OpensslClient {
// certs include multiple certificates. We could add all of them at once,
// but if any of them were already added, openssl would fail to insert all
// of them.
let mut certs = certs;
let mut ssl_connector_builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); let mut ssl_connector_builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
ssl_connector_builder.set_ca_file(ca_file).expect("could not set CA file"); loop {
let token = "-----END CERTIFICATE-----";
if let Some(index) = certs.find(token) {
let (cert, rest) = certs.split_at(index + token.len());
certs = rest;
let cert = x509::X509::from_pem(cert.as_bytes()).unwrap();
ssl_connector_builder.cert_store_mut().add_cert(cert).or_else(|e| {
let v: Option<Option<&str>> = e.errors().iter().nth(0).map(|e| e.reason());
if v == Some(Some("cert already in hash table")) {
warn!("Cert already in hash table. Ignoring.");
// Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
// certificate is already in the store.
Ok(())
} else {
Err(e)
}
}).expect("could not set CA file");
} else {
break;
}
}
ssl_connector_builder.set_cipher_list(DEFAULT_CIPHERS).expect("could not set ciphers"); ssl_connector_builder.set_cipher_list(DEFAULT_CIPHERS).expect("could not set ciphers");
ssl_connector_builder.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION); ssl_connector_builder.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);
let ssl_connector = ssl_connector_builder.build(); let ssl_connector = ssl_connector_builder.build();

View file

@ -2,14 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use net_traits::IncludeSubdomains; use net_traits::IncludeSubdomains;
use net_traits::pub_domains::reg_suffix; use net_traits::pub_domains::reg_suffix;
use serde_json; use serde_json;
use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::collections::HashMap; use std::collections::HashMap;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::from_utf8;
use time; use time;
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Deserialize, Serialize)]
@ -64,15 +63,13 @@ impl HstsList {
} }
/// Create an `HstsList` from the bytes of a JSON preload file. /// Create an `HstsList` from the bytes of a JSON preload file.
pub fn from_preload(preload_content: &[u8]) -> Option<HstsList> { pub fn from_preload(preload_content: &str) -> Option<HstsList> {
#[derive(Deserialize)] #[derive(Deserialize)]
struct HstsEntries { struct HstsEntries {
entries: Vec<HstsEntry>, entries: Vec<HstsEntry>,
} }
let hsts_entries: Option<HstsEntries> = from_utf8(&preload_content) let hsts_entries: Option<HstsEntries> = serde_json::from_str(preload_content).ok();
.ok()
.and_then(|c| serde_json::from_str(c).ok());
hsts_entries.map_or(None, |hsts_entries| { hsts_entries.map_or(None, |hsts_entries| {
let mut hsts_list: HstsList = HstsList::new(); let mut hsts_list: HstsList = HstsList::new();
@ -86,10 +83,8 @@ impl HstsList {
} }
pub fn from_servo_preload() -> HstsList { pub fn from_servo_preload() -> HstsList {
let file_bytes = read_resource_file("hsts_preload.json") let list = resources::read_string(Resource::HstsPreloadList);
.expect("Could not find Servo HSTS preload file"); HstsList::from_preload(&list).expect("Servo HSTS preload file is invalid")
HstsList::from_preload(&file_bytes)
.expect("Servo HSTS preload file is invalid")
} }
pub fn is_host_secure(&self, host: &str) -> bool { pub fn is_host_secure(&self, host: &str) -> bool {

View file

@ -2,20 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use immeta::load_from_buf; use immeta::load_from_buf;
use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError}; use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError};
use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memory}; use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memory};
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageResponder}; use net_traits::image_cache::{CanRequestImages, ImageCache, ImageResponder};
use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState}; use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState};
use net_traits::image_cache::{PendingImageId, UsePlaceholder}; use net_traits::image_cache::{PendingImageId, UsePlaceholder};
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fs::File; use std::io;
use std::io::{self, Read};
use std::mem; use std::mem;
use std::path::PathBuf;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use webrender_api; use webrender_api;
@ -42,11 +40,8 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8]) -> DecoderMsg {
} }
} }
fn get_placeholder_image(webrender_api: &webrender_api::RenderApi, path: &PathBuf) -> io::Result<Arc<Image>> { fn get_placeholder_image(webrender_api: &webrender_api::RenderApi, data: &[u8]) -> io::Result<Arc<Image>> {
let mut file = File::open(path)?; let mut image = load_from_memory(&data).unwrap();
let mut image_data = vec![];
file.read_to_end(&mut image_data)?;
let mut image = load_from_memory(&image_data).unwrap();
set_webrender_image_key(webrender_api, &mut image); set_webrender_image_key(webrender_api, &mut image);
Ok(Arc::new(image)) Ok(Arc::new(image))
} }
@ -403,15 +398,14 @@ impl ImageCache for ImageCacheImpl {
fn new(webrender_api: webrender_api::RenderApi) -> ImageCacheImpl { fn new(webrender_api: webrender_api::RenderApi) -> ImageCacheImpl {
debug!("New image cache"); debug!("New image cache");
let mut placeholder_path = resources_dir_path().expect("Can't figure out resources path."); let rippy_data = resources::read_bytes(Resource::RippyPNG);
placeholder_path.push("rippy.png");
ImageCacheImpl { ImageCacheImpl {
store: Arc::new(Mutex::new(ImageCacheStore { store: Arc::new(Mutex::new(ImageCacheStore {
pending_loads: AllPendingLoads::new(), pending_loads: AllPendingLoads::new(),
completed_loads: HashMap::new(), completed_loads: HashMap::new(),
placeholder_image: get_placeholder_image(&webrender_api, &placeholder_path).ok(), placeholder_image: get_placeholder_image(&webrender_api, &rippy_data).ok(),
placeholder_url: ServoUrl::from_file_path(&placeholder_path).unwrap(), placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(),
webrender_api: webrender_api, webrender_api: webrender_api,
})) }))
} }

View file

@ -8,6 +8,7 @@ extern crate base64;
extern crate brotli; extern crate brotli;
extern crate cookie as cookie_rs; extern crate cookie as cookie_rs;
extern crate devtools_traits; extern crate devtools_traits;
extern crate embedder_traits;
extern crate flate2; extern crate flate2;
extern crate hyper; extern crate hyper;
extern crate hyper_openssl; extern crate hyper_openssl;
@ -44,7 +45,6 @@ extern crate webrender_api;
extern crate websocket; extern crate websocket;
mod blob_loader; mod blob_loader;
mod chrome_loader;
pub mod connector; pub mod connector;
pub mod cookie; pub mod cookie;
pub mod cookie_storage; pub mod cookie_storage;
@ -68,7 +68,6 @@ pub mod fetch {
/// A module for re-exports of items used in unit tests. /// A module for re-exports of items used in unit tests.
pub mod test { pub mod test {
pub use chrome_loader::resolve_chrome_url;
pub use http_loader::HttpState; pub use http_loader::HttpState;
pub use hosts::{replace_host_table, parse_hostsfile}; pub use hosts::{replace_host_table, parse_hostsfile};
} }

View file

@ -8,6 +8,7 @@ use cookie;
use cookie_rs; use cookie_rs;
use cookie_storage::CookieStorage; use cookie_storage::CookieStorage;
use devtools_traits::DevtoolsControlMsg; use devtools_traits::DevtoolsControlMsg;
use embedder_traits::resources::{self, Resource};
use fetch::cors_cache::CorsCache; use fetch::cors_cache::CorsCache;
use fetch::methods::{CancellationListener, FetchContext, fetch}; use fetch::methods::{CancellationListener, FetchContext, fetch};
use filemanager_thread::{FileManager, TFDProvider}; use filemanager_thread::{FileManager, TFDProvider};
@ -31,12 +32,11 @@ use serde::{Deserialize, Serialize};
use serde_json; use serde_json;
use servo_allocator; use servo_allocator;
use servo_config::opts; use servo_config::opts;
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::{Cow, ToOwned}; use std::borrow::{Cow, ToOwned};
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::{self, File};
use std::io::prelude::*; use std::io::prelude::*;
use std::ops::Deref; use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -118,14 +118,16 @@ fn create_http_states(config_dir: Option<&Path>) -> (Arc<HttpState>, Arc<HttpSta
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json"); read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
} }
let ca_file = match opts::get().certificate_path { let certs = match opts::get().certificate_path {
Some(ref path) => PathBuf::from(path), Some(ref path) => {
None => resources_dir_path() fs::read_to_string(path).expect("Couldn't not find certificate file")
.expect("Need certificate file to make network requests") }
.join("certs"), None => {
resources::read_string(Resource::SSLCertificates)
},
}; };
let ssl_client = create_ssl_client(&ca_file); let ssl_client = create_ssl_client(&certs);
let http_state = HttpState { let http_state = HttpState {
cookie_jar: RwLock::new(cookie_jar), cookie_jar: RwLock::new(cookie_jar),
auth_cache: RwLock::new(auth_cache), auth_cache: RwLock::new(auth_cache),
@ -136,7 +138,7 @@ fn create_http_states(config_dir: Option<&Path>) -> (Arc<HttpState>, Arc<HttpSta
connector: create_http_connector(ssl_client), connector: create_http_connector(ssl_client),
}; };
let private_ssl_client = create_ssl_client(&ca_file); let private_ssl_client = create_ssl_client(&certs);
let private_http_state = HttpState::new(private_ssl_client); let private_http_state = HttpState::new(private_ssl_client);
(Arc::new(http_state), Arc::new(private_http_state)) (Arc::new(http_state), Arc::new(private_http_state))

View file

@ -1,44 +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/. */
use net::test::resolve_chrome_url;
use servo_url::ServoUrl;
fn c(s: &str) -> Result<ServoUrl, ()> {
resolve_chrome_url(&ServoUrl::parse(s).unwrap())
}
#[test]
fn test_resolve_chrome_url() {
assert_eq!(c("chrome://resources/nonexistent.jpg"), Err(()));
assert_eq!(c("chrome://not-resources/badcert.jpg"), Err(()));
assert_eq!(c("chrome://resources/badcert.jpg").unwrap().scheme(), "file");
assert_eq!(c("chrome://resources/subdir/../badcert.jpg").unwrap().scheme(), "file");
assert_eq!(c("chrome://resources/subdir/../../badcert.jpg").unwrap().scheme(), "file");
assert_eq!(c("chrome://resources/../badcert.jpg").unwrap().scheme(), "file");
assert_eq!(c("chrome://resources/../README.md"), Err(()));
assert_eq!(c("chrome://resources/%2e%2e/README.md"), Err(()));
assert_eq!(c("chrome://resources/etc/passwd"), Err(()));
assert_eq!(c("chrome://resources//etc/passwd"), Err(()));
assert_eq!(c("chrome://resources/%2Fetc%2Fpasswd"), Err(()));
assert_eq!(c("chrome://resources/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/C:\\Windows\\notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources//localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources///localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/\\\\localhost\\C:\\Windows\\notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/%3F/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources//%3F/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources///%3F/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/\\\\%3F\\C:\\Windows\\notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources//%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources///%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
assert_eq!(c("chrome://resources/\\\\%3F\\UNC\\localhost\\C:\\Windows\\notepad.exe"), Err(()));
}

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cookie_rs; use cookie_rs;
use embedder_traits::resources::register_resources_for_tests;
use hyper::header::{Header, SetCookie}; use hyper::header::{Header, SetCookie};
use net::cookie::Cookie; use net::cookie::Cookie;
use net::cookie_storage::CookieStorage; use net::cookie_storage::CookieStorage;
@ -56,6 +57,7 @@ fn test_default_path() {
#[test] #[test]
fn fn_cookie_constructor() { fn fn_cookie_constructor() {
use net_traits::CookieSource; use net_traits::CookieSource;
register_resources_for_tests();
let url = &ServoUrl::parse("http://example.com/foo").unwrap(); let url = &ServoUrl::parse("http://example.com/foo").unwrap();
@ -102,6 +104,7 @@ fn fn_cookie_constructor() {
#[test] #[test]
fn test_cookie_secure_prefix() { fn test_cookie_secure_prefix() {
register_resources_for_tests();
let url = &ServoUrl::parse("https://example.com").unwrap(); let url = &ServoUrl::parse("https://example.com").unwrap();
let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345").unwrap(); let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345").unwrap();
assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none()); assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
@ -129,6 +132,7 @@ fn test_cookie_secure_prefix() {
#[test] #[test]
fn test_cookie_host_prefix() { fn test_cookie_host_prefix() {
register_resources_for_tests();
let url = &ServoUrl::parse("https://example.com").unwrap(); let url = &ServoUrl::parse("https://example.com").unwrap();
let cookie = cookie_rs::Cookie::parse("__Host-SID=12345").unwrap(); let cookie = cookie_rs::Cookie::parse("__Host-SID=12345").unwrap();
assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none()); assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
@ -182,6 +186,7 @@ fn delay_to_ensure_different_timestamp() {}
#[test] #[test]
fn test_sort_order() { fn test_sort_order() {
use std::cmp::Ordering; use std::cmp::Ordering;
register_resources_for_tests();
let url = &ServoUrl::parse("http://example.com/foo").unwrap(); let url = &ServoUrl::parse("http://example.com/foo").unwrap();
let a_wrapped = cookie_rs::Cookie::parse("baz=bar; Path=/foo/bar/").unwrap(); let a_wrapped = cookie_rs::Cookie::parse("baz=bar; Path=/foo/bar/").unwrap();
@ -201,6 +206,7 @@ fn test_sort_order() {
fn add_cookie_to_storage(storage: &mut CookieStorage, url: &ServoUrl, cookie_str: &str) fn add_cookie_to_storage(storage: &mut CookieStorage, url: &ServoUrl, cookie_str: &str)
{ {
register_resources_for_tests();
let source = CookieSource::HTTP; let source = CookieSource::HTTP;
let cookie = cookie_rs::Cookie::parse(cookie_str.to_owned()).unwrap(); let cookie = cookie_rs::Cookie::parse(cookie_str.to_owned()).unwrap();
let cookie = Cookie::new_wrapped(cookie, url, source).unwrap(); let cookie = Cookie::new_wrapped(cookie, url, source).unwrap();
@ -209,6 +215,7 @@ fn add_cookie_to_storage(storage: &mut CookieStorage, url: &ServoUrl, cookie_str
#[test] #[test]
fn test_insecure_cookies_cannot_evict_secure_cookie() { fn test_insecure_cookies_cannot_evict_secure_cookie() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5); let mut storage = CookieStorage::new(5);
let secure_url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap(); let secure_url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::HTTP; let source = CookieSource::HTTP;
@ -245,6 +252,7 @@ fn test_insecure_cookies_cannot_evict_secure_cookie() {
#[test] #[test]
fn test_secure_cookies_eviction() { fn test_secure_cookies_eviction() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5); let mut storage = CookieStorage::new(5);
let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap(); let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::HTTP; let source = CookieSource::HTTP;
@ -280,6 +288,7 @@ fn test_secure_cookies_eviction() {
#[test] #[test]
fn test_secure_cookies_eviction_non_http_source() { fn test_secure_cookies_eviction_non_http_source() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5); let mut storage = CookieStorage::new(5);
let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap(); let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::NonHTTP; let source = CookieSource::NonHTTP;
@ -341,6 +350,7 @@ fn add_retrieve_cookies(set_location: &str,
#[test] #[test]
fn test_cookie_eviction_expired() { fn test_cookie_eviction_expired() {
register_resources_for_tests();
let mut vec = Vec::new(); let mut vec = Vec::new();
for i in 1..6 { for i in 1..6 {
let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2000 21:06:29 GMT", let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2000 21:06:29 GMT",
@ -356,6 +366,7 @@ fn test_cookie_eviction_expired() {
#[test] #[test]
fn test_cookie_eviction_all_secure_one_nonsecure() { fn test_cookie_eviction_all_secure_one_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new(); let mut vec = Vec::new();
for i in 1..5 { for i in 1..5 {
let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT", let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT",
@ -372,6 +383,7 @@ fn test_cookie_eviction_all_secure_one_nonsecure() {
#[test] #[test]
fn test_cookie_eviction_all_secure_new_nonsecure() { fn test_cookie_eviction_all_secure_new_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new(); let mut vec = Vec::new();
for i in 1..6 { for i in 1..6 {
let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT", let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT",
@ -387,6 +399,7 @@ fn test_cookie_eviction_all_secure_new_nonsecure() {
#[test] #[test]
fn test_cookie_eviction_all_nonsecure_new_secure() { fn test_cookie_eviction_all_nonsecure_new_secure() {
register_resources_for_tests();
let mut vec = Vec::new(); let mut vec = Vec::new();
for i in 1..6 { for i in 1..6 {
let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i); let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i);
@ -401,6 +414,7 @@ fn test_cookie_eviction_all_nonsecure_new_secure() {
#[test] #[test]
fn test_cookie_eviction_all_nonsecure_new_nonsecure() { fn test_cookie_eviction_all_nonsecure_new_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new(); let mut vec = Vec::new();
for i in 1..6 { for i in 1..6 {
let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i); let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i);

View file

@ -6,6 +6,7 @@ use {DEFAULT_USER_AGENT, new_fetch_context, fetch, make_server};
use devtools_traits::DevtoolsControlMsg; use devtools_traits::DevtoolsControlMsg;
use devtools_traits::HttpRequest as DevtoolsHttpRequest; use devtools_traits::HttpRequest as DevtoolsHttpRequest;
use devtools_traits::HttpResponse as DevtoolsHttpResponse; use devtools_traits::HttpResponse as DevtoolsHttpResponse;
use embedder_traits::resources::register_resources_for_tests;
use fetch_with_context; use fetch_with_context;
use fetch_with_cors_cache; use fetch_with_cors_cache;
use http_loader::{expect_devtools_http_request, expect_devtools_http_response}; use http_loader::{expect_devtools_http_request, expect_devtools_http_response};
@ -34,10 +35,10 @@ use net_traits::NetworkError;
use net_traits::ReferrerPolicy; use net_traits::ReferrerPolicy;
use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode}; use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType}; use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
use servo_config::resource_files::resources_dir_path;
use servo_url::{ImmutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, ServoUrl};
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::path::Path;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Sender, channel}; use std::sync::mpsc::{Sender, channel};
@ -48,6 +49,7 @@ use unicase::UniCase;
#[test] #[test]
fn test_fetch_response_is_not_network_error() { fn test_fetch_response_is_not_network_error() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -67,6 +69,7 @@ fn test_fetch_response_is_not_network_error() {
#[test] #[test]
fn test_fetch_on_bad_port_is_network_error() { fn test_fetch_on_bad_port_is_network_error() {
register_resources_for_tests();
let url = ServoUrl::parse("http://www.example.org:6667").unwrap(); let url = ServoUrl::parse("http://www.example.org:6667").unwrap();
let origin = Origin::Origin(url.origin()); let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None); let mut request = Request::new(url, Some(origin), None);
@ -79,6 +82,7 @@ fn test_fetch_on_bad_port_is_network_error() {
#[test] #[test]
fn test_fetch_response_body_matches_const_message() { fn test_fetch_response_body_matches_const_message() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"Hello World!"; static MESSAGE: &'static [u8] = b"Hello World!";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -104,6 +108,7 @@ fn test_fetch_response_body_matches_const_message() {
#[test] #[test]
fn test_fetch_aboutblank() { fn test_fetch_aboutblank() {
register_resources_for_tests();
let url = ServoUrl::parse("about:blank").unwrap(); let url = ServoUrl::parse("about:blank").unwrap();
let origin = Origin::Origin(url.origin()); let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None); let mut request = Request::new(url, Some(origin), None);
@ -115,6 +120,7 @@ fn test_fetch_aboutblank() {
#[test] #[test]
fn test_fetch_blob() { fn test_fetch_blob() {
register_resources_for_tests();
use ipc_channel::ipc; use ipc_channel::ipc;
use net_traits::blob_url_store::BlobBuf; use net_traits::blob_url_store::BlobBuf;
@ -155,9 +161,8 @@ fn test_fetch_blob() {
#[test] #[test]
fn test_fetch_file() { fn test_fetch_file() {
let mut path = resources_dir_path().expect("Cannot find resource dir"); register_resources_for_tests();
path.push("servo.css"); let path = Path::new("../../resources/servo.css").canonicalize().unwrap();
let url = ServoUrl::from_file_path(path.clone()).unwrap(); let url = ServoUrl::from_file_path(path.clone()).unwrap();
let origin = Origin::Origin(url.origin()); let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None); let mut request = Request::new(url, Some(origin), None);
@ -183,6 +188,7 @@ fn test_fetch_file() {
#[test] #[test]
fn test_fetch_ftp() { fn test_fetch_ftp() {
register_resources_for_tests();
let url = ServoUrl::parse("ftp://not-supported").unwrap(); let url = ServoUrl::parse("ftp://not-supported").unwrap();
let origin = Origin::Origin(url.origin()); let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None); let mut request = Request::new(url, Some(origin), None);
@ -193,6 +199,7 @@ fn test_fetch_ftp() {
#[test] #[test]
fn test_fetch_bogus_scheme() { fn test_fetch_bogus_scheme() {
register_resources_for_tests();
let url = ServoUrl::parse("bogus://whatever").unwrap(); let url = ServoUrl::parse("bogus://whatever").unwrap();
let origin = Origin::Origin(url.origin()); let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None); let mut request = Request::new(url, Some(origin), None);
@ -203,6 +210,7 @@ fn test_fetch_bogus_scheme() {
#[test] #[test]
fn test_cors_preflight_fetch() { fn test_cors_preflight_fetch() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK"; static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0)); let state = Arc::new(AtomicUsize::new(0));
let handler = move |request: HyperRequest, mut response: HyperResponse| { let handler = move |request: HyperRequest, mut response: HyperResponse| {
@ -240,6 +248,7 @@ fn test_cors_preflight_fetch() {
#[test] #[test]
fn test_cors_preflight_cache_fetch() { fn test_cors_preflight_cache_fetch() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK"; static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0)); let state = Arc::new(AtomicUsize::new(0));
let counter = state.clone(); let counter = state.clone();
@ -292,6 +301,7 @@ fn test_cors_preflight_cache_fetch() {
#[test] #[test]
fn test_cors_preflight_fetch_network_error() { fn test_cors_preflight_fetch_network_error() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK"; static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0)); let state = Arc::new(AtomicUsize::new(0));
let handler = move |request: HyperRequest, mut response: HyperResponse| { let handler = move |request: HyperRequest, mut response: HyperResponse| {
@ -322,6 +332,7 @@ fn test_cors_preflight_fetch_network_error() {
#[test] #[test]
fn test_fetch_response_is_basic_filtered() { fn test_fetch_response_is_basic_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, mut response: HyperResponse| { let handler = move |_: HyperRequest, mut response: HyperResponse| {
response.headers_mut().set(SetCookie(vec![])); response.headers_mut().set(SetCookie(vec![]));
@ -348,6 +359,7 @@ fn test_fetch_response_is_basic_filtered() {
#[test] #[test]
fn test_fetch_response_is_cors_filtered() { fn test_fetch_response_is_cors_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, mut response: HyperResponse| { let handler = move |_: HyperRequest, mut response: HyperResponse| {
// this is mandatory for the Cors Check to pass // this is mandatory for the Cors Check to pass
@ -402,6 +414,7 @@ fn test_fetch_response_is_cors_filtered() {
#[test] #[test]
fn test_fetch_response_is_opaque_filtered() { fn test_fetch_response_is_opaque_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -435,6 +448,7 @@ fn test_fetch_response_is_opaque_filtered() {
#[test] #[test]
fn test_fetch_response_is_opaque_redirect_filtered() { fn test_fetch_response_is_opaque_redirect_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |request: HyperRequest, mut response: HyperResponse| { let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri { let redirects = match request.uri {
@ -481,6 +495,7 @@ fn test_fetch_response_is_opaque_redirect_filtered() {
#[test] #[test]
fn test_fetch_with_local_urls_only() { fn test_fetch_with_local_urls_only() {
register_resources_for_tests();
// If flag `local_urls_only` is set, fetching a non-local URL must result in network error. // If flag `local_urls_only` is set, fetching a non-local URL must result in network error.
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
@ -519,26 +534,24 @@ fn test_fetch_with_local_urls_only() {
// And make sure to specify `localhost` as the server name. // And make sure to specify `localhost` as the server name.
#[test] #[test]
fn test_fetch_with_hsts() { fn test_fetch_with_hsts() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
}; };
let path = resources_dir_path().expect("Cannot find resource dir"); let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt").canonicalize().unwrap();
let mut cert_path = path.clone(); let key_path = Path::new("../../resources/privatekey_for_testing.key").canonicalize().unwrap();
cert_path.push("self_signed_certificate_for_testing.crt");
let mut key_path = path.clone(); let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path.clone())
key_path.push("privatekey_for_testing.key");
let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path)
.unwrap(); .unwrap();
//takes an address and something that implements hyper::net::Ssl //takes an address and something that implements hyper::net::Ssl
let mut server = Server::https("0.0.0.0:0", ssl).unwrap().handle_threads(handler, 1).unwrap(); let mut server = Server::https("0.0.0.0:0", ssl).unwrap().handle_threads(handler, 1).unwrap();
let ca_file = resources_dir_path().unwrap().join("self_signed_certificate_for_testing.crt"); let mut ca_content = String::new();
let ssl_client = create_ssl_client(&ca_file); File::open(cert_path).unwrap().read_to_string(&mut ca_content).unwrap();
let ssl_client = create_ssl_client(&ca_content);
let context = FetchContext { let context = FetchContext {
state: Arc::new(HttpState::new(ssl_client)), state: Arc::new(HttpState::new(ssl_client)),
@ -568,6 +581,7 @@ fn test_fetch_with_hsts() {
#[test] #[test]
fn test_fetch_with_sri_network_error() { fn test_fetch_with_sri_network_error() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');"; static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -592,6 +606,7 @@ fn test_fetch_with_sri_network_error() {
#[test] #[test]
fn test_fetch_with_sri_sucess() { fn test_fetch_with_sri_sucess() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"alert('Hello, world.');"; static MESSAGE: &'static [u8] = b"alert('Hello, world.');";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -659,6 +674,7 @@ fn test_fetch_blocked_nosniff() {
} }
fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response { fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response {
register_resources_for_tests();
let handler = move |request: HyperRequest, mut response: HyperResponse| { let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri { let redirects = match request.uri {
RequestUri::AbsolutePath(url) => RequestUri::AbsolutePath(url) =>
@ -689,6 +705,7 @@ fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response
#[test] #[test]
fn test_fetch_redirect_count_ceiling() { fn test_fetch_redirect_count_ceiling() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"no more redirects"; static MESSAGE: &'static [u8] = b"no more redirects";
// how many redirects to cause // how many redirects to cause
let redirect_cap = 20; let redirect_cap = 20;
@ -708,6 +725,7 @@ fn test_fetch_redirect_count_ceiling() {
#[test] #[test]
fn test_fetch_redirect_count_failure() { fn test_fetch_redirect_count_failure() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"this message shouldn't be reachable"; static MESSAGE: &'static [u8] = b"this message shouldn't be reachable";
// how many redirects to cause // how many redirects to cause
let redirect_cap = 21; let redirect_cap = 21;
@ -773,6 +791,7 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender<bool>, status_code: Stat
#[test] #[test]
fn test_fetch_redirect_updates_method() { fn test_fetch_redirect_updates_method() {
register_resources_for_tests();
let (tx, rx) = channel(); let (tx, rx) = channel();
test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, Method::Post); test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, Method::Post);
@ -831,6 +850,7 @@ fn response_is_done(response: &Response) -> bool {
#[test] #[test]
fn test_fetch_async_returns_complete_response() { fn test_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"this message should be retrieved in full"; static MESSAGE: &'static [u8] = b"this message should be retrieved in full";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -849,6 +869,7 @@ fn test_fetch_async_returns_complete_response() {
#[test] #[test]
fn test_opaque_filtered_fetch_async_returns_complete_response() { fn test_opaque_filtered_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();
@ -870,6 +891,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() {
#[test] #[test]
fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() { fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b""; static MESSAGE: &'static [u8] = b"";
let handler = move |request: HyperRequest, mut response: HyperResponse| { let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri { let redirects = match request.uri {
@ -906,6 +928,7 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
#[test] #[test]
fn test_fetch_with_devtools() { fn test_fetch_with_devtools() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"Yay!"; static MESSAGE: &'static [u8] = b"Yay!";
let handler = move |_: HyperRequest, response: HyperResponse| { let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap(); response.send(MESSAGE).unwrap();

View file

@ -176,24 +176,24 @@ fn test_push_entry_to_hsts_list_should_add_an_entry() {
#[test] #[test]
fn test_parse_hsts_preload_should_return_none_when_json_invalid() { fn test_parse_hsts_preload_should_return_none_when_json_invalid() {
let mock_preload_content = b"derp"; let mock_preload_content = "derp";
assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed") assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
} }
#[test] #[test]
fn test_parse_hsts_preload_should_return_none_when_json_contains_no_entries_map_key() { fn test_parse_hsts_preload_should_return_none_when_json_contains_no_entries_map_key() {
let mock_preload_content = b"{\"nothing\": \"to see here\"}"; let mock_preload_content = "{\"nothing\": \"to see here\"}";
assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed") assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
} }
#[test] #[test]
fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() { fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() {
let mock_preload_content = b"{\ let mock_preload_content = "{\
\"entries\": [\ \"entries\": [\
{\"host\": \"mozilla.org\",\ {\"host\": \"mozilla.org\",\
\"include_subdomains\": false}\ \"include_subdomains\": false}\
]\ ]\
}"; }";
let hsts_list = HstsList::from_preload(mock_preload_content); let hsts_list = HstsList::from_preload(mock_preload_content);
let entries_map = hsts_list.unwrap().entries_map; let entries_map = hsts_list.unwrap().entries_map;

View file

@ -6,6 +6,7 @@ use cookie_rs::Cookie as CookiePair;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent};
use devtools_traits::HttpRequest as DevtoolsHttpRequest; use devtools_traits::HttpRequest as DevtoolsHttpRequest;
use devtools_traits::HttpResponse as DevtoolsHttpResponse; use devtools_traits::HttpResponse as DevtoolsHttpResponse;
use embedder_traits::resources::register_resources_for_tests;
use fetch; use fetch;
use fetch_with_context; use fetch_with_context;
use flate2::Compression; use flate2::Compression;
@ -312,6 +313,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
#[test] #[test]
fn test_redirected_request_to_devtools() { fn test_redirected_request_to_devtools() {
register_resources_for_tests();
let post_handler = move |request: HyperRequest, response: HyperResponse| { let post_handler = move |request: HyperRequest, response: HyperResponse| {
assert_eq!(request.method, Method::Get); assert_eq!(request.method, Method::Get);
response.send(b"Yay!").unwrap(); response.send(b"Yay!").unwrap();

View file

@ -6,6 +6,7 @@
extern crate cookie as cookie_rs; extern crate cookie as cookie_rs;
extern crate devtools_traits; extern crate devtools_traits;
extern crate embedder_traits;
extern crate flate2; extern crate flate2;
extern crate hyper; extern crate hyper;
extern crate hyper_openssl; extern crate hyper_openssl;
@ -15,13 +16,11 @@ extern crate msg;
extern crate net; extern crate net;
extern crate net_traits; extern crate net_traits;
extern crate profile_traits; extern crate profile_traits;
extern crate servo_config;
extern crate servo_url; extern crate servo_url;
extern crate time; extern crate time;
extern crate unicase; extern crate unicase;
extern crate url; extern crate url;
mod chrome_loader;
mod cookie; mod cookie;
mod cookie_http_state; mod cookie_http_state;
mod data_loader; mod data_loader;
@ -35,6 +34,7 @@ mod resource_thread;
mod subresource_integrity; mod subresource_integrity;
use devtools_traits::DevtoolsControlMsg; use devtools_traits::DevtoolsControlMsg;
use embedder_traits::resources::{self, Resource};
use hyper::server::{Handler, Listening, Server}; use hyper::server::{Handler, Listening, Server};
use net::connector::create_ssl_client; use net::connector::create_ssl_client;
use net::fetch::cors_cache::CorsCache; use net::fetch::cors_cache::CorsCache;
@ -44,7 +44,6 @@ use net::test::HttpState;
use net_traits::FetchTaskTarget; use net_traits::FetchTaskTarget;
use net_traits::request::Request; use net_traits::request::Request;
use net_traits::response::Response; use net_traits::response::Response;
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::mpsc::{Sender, channel}; use std::sync::mpsc::{Sender, channel};
@ -56,8 +55,7 @@ struct FetchResponseCollector {
} }
fn new_fetch_context(dc: Option<Sender<DevtoolsControlMsg>>) -> FetchContext { fn new_fetch_context(dc: Option<Sender<DevtoolsControlMsg>>) -> FetchContext {
let ca_file = resources_dir_path().unwrap().join("certs"); let ssl_client = create_ssl_client(&resources::read_string(Resource::SSLCertificates));
let ssl_client = create_ssl_client(&ca_file);
FetchContext { FetchContext {
state: Arc::new(HttpState::new(ssl_client)), state: Arc::new(HttpState::new(ssl_client)),
user_agent: DEFAULT_USER_AGENT.into(), user_agent: DEFAULT_USER_AGENT.into(),

View file

@ -13,6 +13,7 @@ doctest = false
[dependencies] [dependencies]
cookie = "0.10" cookie = "0.10"
embedder_traits = { path = "../embedder_traits" }
hyper = "0.10" hyper = "0.10"
hyper_serde = "0.8" hyper_serde = "0.8"
image = "0.18" image = "0.18"

View file

@ -6,6 +6,7 @@
#![deny(unsafe_code)] #![deny(unsafe_code)]
extern crate cookie as cookie_rs; extern crate cookie as cookie_rs;
extern crate embedder_traits;
extern crate hyper; extern crate hyper;
extern crate hyper_serde; extern crate hyper_serde;
extern crate image as piston_image; extern crate image as piston_image;
@ -18,7 +19,6 @@ extern crate msg;
extern crate num_traits; extern crate num_traits;
#[macro_use] extern crate serde; #[macro_use] extern crate serde;
extern crate servo_arc; extern crate servo_arc;
extern crate servo_config;
extern crate servo_url; extern crate servo_url;
extern crate url; extern crate url;
extern crate uuid; extern crate uuid;

View file

@ -14,11 +14,10 @@
//! we don't need to make the code more complex for it. The `mach` update command makes sure that //! we don't need to make the code more complex for it. The `mach` update command makes sure that
//! those cases are not present. //! those cases are not present.
use servo_config::resource_files::read_resource_file; use embedder_traits::resources::{self, Resource};
use servo_url::{Host, ImmutableOrigin, ServoUrl}; use servo_url::{Host, ImmutableOrigin, ServoUrl};
use std::collections::HashSet; use std::collections::HashSet;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::str::from_utf8;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PubDomainRules { pub struct PubDomainRules {
@ -121,9 +120,7 @@ impl PubDomainRules {
} }
fn load_pub_domains() -> PubDomainRules { fn load_pub_domains() -> PubDomainRules {
let content = read_resource_file("public_domains.txt").expect("Could not find public suffix list file"); PubDomainRules::parse(&resources::read_string(Resource::DomainList))
let content = from_utf8(&content).expect("Could not read public suffix list file");
PubDomainRules::parse(content)
} }
pub fn pub_suffix(domain: &str) -> &str { pub fn pub_suffix(domain: &str) -> &str {

View file

@ -2,14 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate net_traits; extern crate net_traits;
use embedder_traits::resources::register_resources_for_tests;
use net_traits::pub_domains::{is_pub_domain, is_reg_domain, pub_suffix, reg_suffix}; use net_traits::pub_domains::{is_pub_domain, is_reg_domain, pub_suffix, reg_suffix};
// These tests may need to be updated if the PSL changes. // These tests may need to be updated if the PSL changes.
#[test] #[test]
fn test_is_pub_domain_plain() { fn test_is_pub_domain_plain() {
register_resources_for_tests();
assert!(is_pub_domain("com")); assert!(is_pub_domain("com"));
assert!(is_pub_domain(".org")); assert!(is_pub_domain(".org"));
assert!(is_pub_domain("za.org")); assert!(is_pub_domain("za.org"));
@ -19,6 +22,7 @@ fn test_is_pub_domain_plain() {
#[test] #[test]
fn test_is_pub_domain_wildcard() { fn test_is_pub_domain_wildcard() {
register_resources_for_tests();
assert!(is_pub_domain("hello.bd")); assert!(is_pub_domain("hello.bd"));
assert!(is_pub_domain("world.jm")); assert!(is_pub_domain("world.jm"));
assert!(is_pub_domain("toto.kobe.jp")); assert!(is_pub_domain("toto.kobe.jp"));
@ -26,6 +30,7 @@ fn test_is_pub_domain_wildcard() {
#[test] #[test]
fn test_is_pub_domain_exception() { fn test_is_pub_domain_exception() {
register_resources_for_tests();
assert_eq!(is_pub_domain("www.ck"), false); assert_eq!(is_pub_domain("www.ck"), false);
assert_eq!(is_pub_domain("city.kawasaki.jp"), false); assert_eq!(is_pub_domain("city.kawasaki.jp"), false);
assert_eq!(is_pub_domain("city.nagoya.jp"), false); assert_eq!(is_pub_domain("city.nagoya.jp"), false);
@ -34,6 +39,7 @@ fn test_is_pub_domain_exception() {
#[test] #[test]
fn test_is_pub_domain_not() { fn test_is_pub_domain_not() {
register_resources_for_tests();
assert_eq!(is_pub_domain(""), false); assert_eq!(is_pub_domain(""), false);
assert_eq!(is_pub_domain("."), false); assert_eq!(is_pub_domain("."), false);
assert_eq!(is_pub_domain("..."), false); assert_eq!(is_pub_domain("..."), false);
@ -46,6 +52,7 @@ fn test_is_pub_domain_not() {
#[test] #[test]
fn test_is_pub_domain() { fn test_is_pub_domain() {
register_resources_for_tests();
assert!(!is_pub_domain("city.yokohama.jp")); assert!(!is_pub_domain("city.yokohama.jp"));
assert!(!is_pub_domain("foo.bar.baz.yokohama.jp")); assert!(!is_pub_domain("foo.bar.baz.yokohama.jp"));
assert!(!is_pub_domain("foo.bar.city.yokohama.jp")); assert!(!is_pub_domain("foo.bar.city.yokohama.jp"));
@ -64,6 +71,7 @@ fn test_is_pub_domain() {
#[test] #[test]
fn test_is_reg_domain() { fn test_is_reg_domain() {
register_resources_for_tests();
assert!(!is_reg_domain("com")); assert!(!is_reg_domain("com"));
assert!(!is_reg_domain("foo.bar.baz.yokohama.jp")); assert!(!is_reg_domain("foo.bar.baz.yokohama.jp"));
assert!(!is_reg_domain("foo.bar.com")); assert!(!is_reg_domain("foo.bar.com"));
@ -81,6 +89,7 @@ fn test_is_reg_domain() {
#[test] #[test]
fn test_pub_suffix() { fn test_pub_suffix() {
register_resources_for_tests();
assert_eq!(pub_suffix("city.yokohama.jp"), "yokohama.jp"); assert_eq!(pub_suffix("city.yokohama.jp"), "yokohama.jp");
assert_eq!(pub_suffix("com"), "com"); assert_eq!(pub_suffix("com"), "com");
assert_eq!(pub_suffix("foo.bar.baz.yokohama.jp"), "baz.yokohama.jp"); assert_eq!(pub_suffix("foo.bar.baz.yokohama.jp"), "baz.yokohama.jp");
@ -98,6 +107,7 @@ fn test_pub_suffix() {
#[test] #[test]
fn test_reg_suffix() { fn test_reg_suffix() {
register_resources_for_tests();
assert_eq!(reg_suffix("city.yokohama.jp"), "city.yokohama.jp"); assert_eq!(reg_suffix("city.yokohama.jp"), "city.yokohama.jp");
assert_eq!(reg_suffix("com"), "com"); assert_eq!(reg_suffix("com"), "com");
assert_eq!(reg_suffix("foo.bar.baz.yokohama.jp"), "bar.baz.yokohama.jp"); assert_eq!(reg_suffix("foo.bar.baz.yokohama.jp"), "bar.baz.yokohama.jp");
@ -115,6 +125,7 @@ fn test_reg_suffix() {
#[test] #[test]
fn test_weirdness() { fn test_weirdness() {
register_resources_for_tests();
// These are weird results, but AFAICT they are spec-compliant. // These are weird results, but AFAICT they are spec-compliant.
assert_ne!(pub_suffix("city.yokohama.jp"), pub_suffix(pub_suffix("city.yokohama.jp"))); assert_ne!(pub_suffix("city.yokohama.jp"), pub_suffix(pub_suffix("city.yokohama.jp")));
assert!(!is_pub_domain(pub_suffix("city.yokohama.jp"))); assert!(!is_pub_domain(pub_suffix("city.yokohama.jp")));

View file

@ -42,6 +42,7 @@ deny_public_fields = {path = "../deny_public_fields"}
devtools_traits = {path = "../devtools_traits"} devtools_traits = {path = "../devtools_traits"}
dom_struct = {path = "../dom_struct"} dom_struct = {path = "../dom_struct"}
domobject_derive = {path = "../domobject_derive"} domobject_derive = {path = "../domobject_derive"}
embedder_traits = {path = "../embedder_traits"}
encoding_rs = "0.7" encoding_rs = "0.7"
euclid = "0.17" euclid = "0.17"
fnv = "1.0" fnv = "1.0"

View file

@ -30,6 +30,7 @@ use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text; use dom::text::Text;
use dom::virtualmethods::vtable_for; use dom::virtualmethods::vtable_for;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::resources::{self, Resource};
use html5ever::{Attribute, ExpandedName, LocalName, QualName}; use html5ever::{Attribute, ExpandedName, LocalName, QualName};
use html5ever::buffer_queue::BufferQueue; use html5ever::buffer_queue::BufferQueue;
use html5ever::tendril::{StrTendril, ByteTendril, IncompleteUtf8}; use html5ever::tendril::{StrTendril, ByteTendril, IncompleteUtf8};
@ -45,7 +46,6 @@ use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile};
use script_thread::ScriptThread; use script_thread::ScriptThread;
use script_traits::DocumentActivity; use script_traits::DocumentActivity;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::Cell; use std::cell::Cell;
@ -671,16 +671,14 @@ impl FetchResponseListener for ParserContext {
// Handle text/html // Handle text/html
if let Some(reason) = ssl_error { if let Some(reason) = ssl_error {
self.is_synthesized_document = true; self.is_synthesized_document = true;
let page_bytes = read_resource_file("badcert.html").unwrap(); let page = resources::read_string(Resource::BadCertHTML);
let page = String::from_utf8(page_bytes).unwrap();
let page = page.replace("${reason}", &reason); let page = page.replace("${reason}", &reason);
parser.push_string_input_chunk(page); parser.push_string_input_chunk(page);
parser.parse_sync(); parser.parse_sync();
} }
if let Some(reason) = network_error { if let Some(reason) = network_error {
self.is_synthesized_document = true; self.is_synthesized_document = true;
let page_bytes = read_resource_file("neterror.html").unwrap(); let page = resources::read_string(Resource::NetErrorHTML);
let page = String::from_utf8(page_bytes).unwrap();
let page = page.replace("${reason}", &reason); let page = page.replace("${reason}", &reason);
parser.push_string_input_chunk(page); parser.push_string_input_chunk(page);
parser.parse_sync(); parser.parse_sync();

View file

@ -8,7 +8,6 @@ use dom::htmlheadelement::HTMLHeadElement;
use dom::node::Node; use dom::node::Node;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use servo_config::opts; use servo_config::opts;
use servo_config::resource_files::resources_dir_path;
use std::fs::{File, read_dir}; use std::fs::{File, read_dir};
use std::io::Read; use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
@ -22,17 +21,7 @@ pub fn load_script(head: &HTMLHeadElement) {
let cx = win.get_cx(); let cx = win.get_cx();
rooted!(in(cx) let mut rval = UndefinedValue()); rooted!(in(cx) let mut rval = UndefinedValue());
let path = if &**path_str == "" { let path = PathBuf::from(path_str);
if let Ok(mut p) = resources_dir_path() {
p.push("user-agent-js");
p
} else {
return
}
} else {
PathBuf::from(path_str)
};
let mut files = read_dir(&path).expect("Bad path passed to --userscripts") let mut files = read_dir(&path).expect("Bad path passed to --userscripts")
.filter_map(|e| e.ok()) .filter_map(|e| e.ok())
.map(|e| e.path()).collect::<Vec<_>>(); .map(|e| e.path()).collect::<Vec<_>>();

View file

@ -35,6 +35,7 @@ extern crate devtools_traits;
extern crate dom_struct; extern crate dom_struct;
#[macro_use] #[macro_use]
extern crate domobject_derive; extern crate domobject_derive;
extern crate embedder_traits;
extern crate encoding_rs; extern crate encoding_rs;
extern crate euclid; extern crate euclid;
extern crate fnv; extern crate fnv;

View file

@ -37,6 +37,7 @@ constellation = {path = "../constellation"}
debugger = {path = "../debugger"} debugger = {path = "../debugger"}
devtools = {path = "../devtools"} devtools = {path = "../devtools"}
devtools_traits = {path = "../devtools_traits"} devtools_traits = {path = "../devtools_traits"}
embedder_traits = {path = "../embedder_traits"}
env_logger = "0.5" env_logger = "0.5"
euclid = "0.17" euclid = "0.17"
gfx = {path = "../gfx"} gfx = {path = "../gfx"}

View file

@ -33,6 +33,7 @@ pub extern crate constellation;
pub extern crate debugger; pub extern crate debugger;
pub extern crate devtools; pub extern crate devtools;
pub extern crate devtools_traits; pub extern crate devtools_traits;
pub extern crate embedder_traits;
pub extern crate euclid; pub extern crate euclid;
pub extern crate gfx; pub extern crate gfx;
pub extern crate ipc_channel; pub extern crate ipc_channel;
@ -95,7 +96,6 @@ use profile_traits::time;
use script_traits::{ConstellationMsg, SWManagerSenders, ScriptToConstellationChan}; use script_traits::{ConstellationMsg, SWManagerSenders, ScriptToConstellationChan};
use servo_config::opts; use servo_config::opts;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_config::resource_files::resources_dir_path;
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::max; use std::cmp::max;
use std::path::PathBuf; use std::path::PathBuf;
@ -154,9 +154,6 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
devtools::start_server(port) devtools::start_server(port)
}); });
let mut resource_path = resources_dir_path().unwrap();
resource_path.push("shaders");
let coordinates = window.get_coordinates(); let coordinates = window.get_coordinates();
let (mut webrender, webrender_api_sender) = { let (mut webrender, webrender_api_sender) = {
@ -181,7 +178,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
webrender::Renderer::new(window.gl(), render_notifier, webrender::RendererOptions { webrender::Renderer::new(window.gl(), render_notifier, webrender::RendererOptions {
device_pixel_ratio: coordinates.hidpi_factor.get(), device_pixel_ratio: coordinates.hidpi_factor.get(),
resource_override_path: Some(resource_path), resource_override_path: opts.shaders_dir.clone(),
enable_aa: opts.enable_text_antialiasing, enable_aa: opts.enable_text_antialiasing,
debug_flags: debug_flags, debug_flags: debug_flags,
recorder: recorder, recorder: recorder,

View file

@ -39,6 +39,7 @@ bitflags = "1.0"
euclid = "0.17" euclid = "0.17"
gleam = "0.4.34" gleam = "0.4.34"
glutin = "0.13" glutin = "0.13"
lazy_static = "1"
libservo = {path = "../../components/servo"} libservo = {path = "../../components/servo"}
log = "0.4" log = "0.4"
tinyfiledialogs = "3.0" tinyfiledialogs = "3.0"

View file

@ -25,6 +25,8 @@ extern crate euclid;
#[cfg(target_os = "windows")] extern crate gdi32; #[cfg(target_os = "windows")] extern crate gdi32;
extern crate gleam; extern crate gleam;
extern crate glutin; extern crate glutin;
#[cfg(not(target_os = "android"))]
#[macro_use] extern crate lazy_static;
// The window backed by glutin // The window backed by glutin
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys; #[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys;
@ -38,6 +40,7 @@ extern crate winit;
#[cfg(target_os = "windows")] extern crate user32; #[cfg(target_os = "windows")] extern crate user32;
mod glutin_app; mod glutin_app;
mod resources;
use backtrace::Backtrace; use backtrace::Backtrace;
use servo::Servo; use servo::Servo;
@ -99,14 +102,16 @@ fn install_crash_handler() {}
fn main() { fn main() {
install_crash_handler(); install_crash_handler();
resources::init();
// Parse the command line options and store them globally // Parse the command line options and store them globally
let opts_result = opts::from_cmdline_args(&*args()); let opts_result = opts::from_cmdline_args(&*args());
let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result { let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
Some(token) Some(token)
} else { } else {
if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() { if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() {
::std::env::set_var("RUST_LOG", "compositing::constellation"); env::set_var("RUST_LOG", "compositing::constellation");
} }
None None
@ -217,7 +222,7 @@ fn main() {
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
fn setup_logging() { fn setup_logging() {
// Piping logs from stdout/stderr to logcat happens in android_injected_glue. // Piping logs from stdout/stderr to logcat happens in android_injected_glue.
::std::env::set_var("RUST_LOG", "error"); env::set_var("RUST_LOG", "error");
unsafe { android_injected_glue::ffi::app_dummy() }; unsafe { android_injected_glue::ffi::app_dummy() };
} }
@ -263,7 +268,6 @@ fn args() -> Vec<String> {
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
fn args() -> Vec<String> { fn args() -> Vec<String> {
use std::env;
env::args().collect() env::args().collect()
} }

112
ports/servo/resources.rs Normal file
View file

@ -0,0 +1,112 @@
/* 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 servo::embedder_traits::resources::{self, Resource};
struct ResourceReader;
fn filename(file: Resource) -> &'static str {
match file {
Resource::Preferences => "prefs.json",
Resource::BluetoothBlocklist => "gatt_blocklist.txt",
Resource::DomainList => "public_domains.txt",
Resource::HstsPreloadList => "hsts_preload.json",
Resource::SSLCertificates => "certs",
Resource::BadCertHTML => "badcert.html",
Resource::NetErrorHTML => "neterror.html",
Resource::UserAgentCSS => "user-agent.css",
Resource::ServoCSS => "servo.css",
Resource::PresentationalHintsCSS => "presentational-hints.css",
Resource::QuirksModeCSS => "quirks-mode.css",
Resource::RippyPNG => "rippy.png",
}
}
pub fn init() {
resources::set(Box::new(ResourceReader));
}
#[cfg(not(target_os = "android"))]
mod not_android {
use servo::embedder_traits::resources::{self, Resource};
use std::env;
use std::fs;
use std::io;
use std::path::PathBuf;
use std::sync::Mutex;
lazy_static! {
static ref CMD_RESOURCE_DIR: Mutex<Option<String>> = Mutex::new(None);
}
impl resources::ResourceReaderMethods for super::ResourceReader {
fn read(&self, file: Resource) -> Vec<u8> {
let file = super::filename(file);
let mut path = resources_dir_path().expect("Can't find resources directory");
path.push(file);
fs::read(path).expect("Can't read file")
}
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
vec![resources_dir_path().expect("Can't find resources directory")]
}
fn sandbox_access_files(&self) -> Vec<PathBuf> {
vec![]
}
}
fn resources_dir_path() -> io::Result<PathBuf> {
// This needs to be called before the process is sandboxed
// as we only give permission to read inside the resources directory,
// not the permissions the "search" for the resources directory.
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)
}
}
#[cfg(target_os = "android")]
mod android {
use android_injected_glue::load_asset;
use servo::embedder_traits::resources::{self, Resource};
use std::path::PathBuf;
impl resources::ResourceReaderMethods for super::ResourceReader {
fn read(&self, file: Resource) -> Vec<u8> {
let file = super::filename(file);
load_asset(file).unwrap_or_else(|_| {
panic!("Can't load asset");
})
}
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
vec![]
}
fn sandbox_access_files(&self) -> Vec<PathBuf> {
vec![]
}
}
}

View file

@ -3,7 +3,6 @@
<title>Certificate error</title> <title>Certificate error</title>
</head> </head>
<body> <body>
<img src="chrome://resources/itried.jpg">
<p>${reason}</p> <p>${reason}</p>
</body> </body>
</html> </html>

View file

@ -1,8 +0,0 @@
<html>
<head>
<title>about:failure</title>
</head>
<body>
<img src="itried.jpg"/>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View file

@ -52,12 +52,6 @@ public class MainActivity extends android.app.NativeActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
try {
extractAssets();
} catch (IOException e) {
throw new RuntimeException(e);
}
final Intent intent = getIntent(); final Intent intent = getIntent();
if (intent != null && intent.getAction().equals(Intent.ACTION_VIEW)) { if (intent != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
final String url = intent.getDataString(); final String url = intent.getDataString();
@ -223,81 +217,10 @@ public class MainActivity extends android.app.NativeActivity {
} }
} }
private boolean needsToExtractAssets(String path) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int version = BuildConfig.VERSION_CODE;
if (!new File(path).exists()) {
// Assets folder doesn't exist, resources need to be copied
prefs.edit().putInt(PREF_KEY_RESOURCES_SYNC, version).apply();
return true;
}
if (version != prefs.getInt(PREF_KEY_RESOURCES_SYNC, -1)) {
// Also force a reextract when the version changes and the resources may be updated
// This can be improved by generating a hash or version number of the resources
// instead of using version code of the app
prefs.edit().putInt(PREF_KEY_RESOURCES_SYNC, version).apply();
return true;
}
return false;
}
private File getAppDataDir() { private File getAppDataDir() {
File file = getExternalFilesDir(null); File file = getExternalFilesDir(null);
return file != null ? file : getFilesDir(); return file != null ? file : getFilesDir();
} }
/**
* extracts assets/ in the APK to /sdcard/servo.
*/
private void extractAssets() throws IOException {
String path = getAppDataDir().getAbsolutePath();
if (!needsToExtractAssets(path)) {
return;
}
ZipFile zipFile = null;
File targetDir = new File(path);
try {
zipFile = new ZipFile(this.getApplicationInfo().sourceDir);
for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) {
ZipEntry entry = e.nextElement();
if (entry.isDirectory() || !entry.getName().startsWith("assets/")) {
continue;
}
File targetFile = new File(targetDir, entry.getName().substring("assets/".length()));
targetFile.getParentFile().mkdirs();
byte[] tempBuffer = new byte[(int)entry.getSize()];
BufferedInputStream is = null;
FileOutputStream os = null;
try {
is = new BufferedInputStream(zipFile.getInputStream(entry));
os = new FileOutputStream(targetFile);
is.read(tempBuffer);
os.write(tempBuffer);
} finally {
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (Exception ex) {
Log.e(LOGTAG, Log.getStackTraceString(ex));
}
}
}
} finally {
try {
if (zipFile != null) {
zipFile.close();
}
} catch (Exception e) {
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
}
private void set_url(String url) { private void set_url(String url) {
try { try {

View file

@ -13,6 +13,7 @@ doctest = false
byteorder = "1.0" byteorder = "1.0"
app_units = "0.6" app_units = "0.6"
cssparser = "0.23.0" cssparser = "0.23.0"
embedder_traits = {path = "../../../components/embedder_traits"}
euclid = "0.17" euclid = "0.17"
html5ever = "0.22" html5ever = "0.22"
parking_lot = "0.5" parking_lot = "0.5"

View file

@ -7,6 +7,7 @@
extern crate app_units; extern crate app_units;
extern crate cssparser; extern crate cssparser;
extern crate embedder_traits;
extern crate euclid; extern crate euclid;
#[macro_use] extern crate html5ever; #[macro_use] extern crate html5ever;
extern crate parking_lot; extern crate parking_lot;

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::{self, SourceLocation}; use cssparser::{self, SourceLocation};
use embedder_traits::resources::register_resources_for_tests;
use html5ever::{Namespace as NsAtom}; use html5ever::{Namespace as NsAtom};
use media_queries::CSSErrorReporterTest; use media_queries::CSSErrorReporterTest;
use parking_lot::RwLock; use parking_lot::RwLock;
@ -321,6 +322,7 @@ impl ParseErrorReporter for TestingErrorReporter {
#[test] #[test]
fn test_report_error_stylesheet() { fn test_report_error_stylesheet() {
register_resources_for_tests();
PREFS.set("layout.viewport.enabled", PrefValue::Boolean(true)); PREFS.set("layout.viewport.enabled", PrefValue::Boolean(true));
let css = r" let css = r"
div { div {