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"
version = "0.0.1"
dependencies = [
"embedder_traits 0.0.1",
"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)",
"serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
]
[[package]]
@ -452,6 +452,7 @@ dependencies = [
"compositing 0.0.1",
"debugger 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)",
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
"gfx 0.0.1",
@ -782,6 +783,13 @@ name = "either"
version = "1.1.0"
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]]
name = "encoding_rs"
version = "0.7.1"
@ -1453,6 +1461,7 @@ version = "0.0.1"
dependencies = [
"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)",
"embedder_traits 0.0.1",
"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)",
"gfx 0.0.1",
@ -1563,6 +1572,7 @@ dependencies = [
"debugger 0.0.1",
"devtools 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)",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"devtools_traits 0.0.1",
"embedder_traits 0.0.1",
"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-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1932,6 +1943,7 @@ name = "net_traits"
version = "0.0.1"
dependencies = [
"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_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)",
@ -2510,6 +2522,7 @@ dependencies = [
"devtools_traits 0.0.1",
"dom_struct 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)",
"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)",
@ -2736,6 +2749,7 @@ dependencies = [
"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)",
"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",
"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)",
@ -2852,6 +2866,7 @@ name = "servo_config"
version = "0.0.1"
dependencies = [
"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)",
"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)",
@ -3078,6 +3093,7 @@ dependencies = [
"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)",
"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)",
"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)",

View file

@ -13,4 +13,4 @@ path = "lib.rs"
ipc-channel = "0.10"
regex = "0.2"
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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use regex::Regex;
use servo_config::resource_files::read_resource_file;
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::BufRead;
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_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}";
@ -75,15 +72,11 @@ impl BluetoothBlocklist {
fn parse_blocklist() -> Option<HashMap<String, Blocklist>> {
// Step 1 missing, currently we parse ./resources/gatt_blocklist.txt.
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
let mut result = HashMap::new();
// Step 2 and 4
for line in content.lines() {
let line = match line {
Ok(l) => l,
Err(_) => return None,
};
// Step 4.1
if line.is_empty() || line.starts_with('#') {
continue;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,83 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#[cfg(target_os = "android")]
use android_injected_glue;
#[cfg(not(target_os = "android"))]
use std::env;
#[cfg(target_os = "android")]
use std::ffi::CStr;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
lazy_static! {
static ref CMD_RESOURCE_DIR: Arc<Mutex<Option<String>>> = {
Arc::new(Mutex::new(None))
};
}
pub fn set_resources_path(path: Option<String>) {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
*dir = path;
}
#[cfg(target_os = "android")]
#[allow(unsafe_code)]
pub fn resources_dir_path() -> io::Result<PathBuf> {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
if let Some(ref path) = *dir {
return Ok(PathBuf::from(path));
}
let data_path = unsafe {
CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
};
let path = PathBuf::from(data_path.to_str().unwrap());
*dir = Some(path.to_str().unwrap().to_owned());
Ok(path)
}
#[cfg(not(target_os = "android"))]
pub fn resources_dir_path() -> io::Result<PathBuf> {
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
if let Some(ref path) = *dir {
return Ok(PathBuf::from(path));
}
// FIXME: Find a way to not rely on the executable being
// under `<servo source>[/$target_triple]/target/debug`
// or `<servo source>[/$target_triple]/target/release`.
let mut path = env::current_exe()?;
// Follow symlink
path = path.canonicalize()?;
while path.pop() {
path.push("resources");
if path.is_dir() {
break;
}
path.pop();
// Check for Resources on mac when using a case sensitive filesystem.
path.push("Resources");
if path.is_dir() {
break;
}
path.pop();
}
*dir = Some(path.to_str().unwrap().to_owned());
Ok(path)
}
pub fn read_resource_file<P: AsRef<Path>>(relative_path: P) -> io::Result<Vec<u8>> {
let mut path = resources_dir_path()?;
path.push(relative_path);
let mut file = File::open(&path)?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
Ok(data)
}

View file

@ -2,8 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate servo_config;
use embedder_traits::resources::register_resources_for_tests;
use servo_config::opts::{parse_url_or_filename, parse_pref_from_command_line};
use servo_config::prefs::{PrefValue, PREFS};
use std::path::Path;
@ -73,6 +75,7 @@ fn test_argument_parsing_special() {
#[test]
fn test_parse_pref_from_command_line() {
register_resources_for_tests();
// Test with boolean values.
parse_pref_from_command_line("testtrue=true");
assert_eq!(*PREFS.get("testtrue"), PrefValue::Boolean(true));

View file

@ -2,10 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_traits;
extern crate servo_config;
use embedder_traits::resources::register_resources_for_tests;
use servo_config::basedir;
use servo_config::prefs::{PREFS, PrefValue, read_prefs_from_file};
use servo_config::prefs::{PREFS, PrefValue, read_prefs};
use std::fs::{self, File};
use std::io::{Read, Write};
@ -17,7 +19,7 @@ fn test_create_pref() {
\"shell.homepage\": \"https://servo.org\"\
}";
let prefs = read_prefs_from_file(json_str.as_bytes());
let prefs = read_prefs(json_str);
assert!(prefs.is_ok());
let prefs = prefs.unwrap();
@ -26,6 +28,7 @@ fn test_create_pref() {
#[test]
fn test_get_set_reset_extend() {
register_resources_for_tests();
let json_str = "{\
\"layout.writing-mode.enabled\": true,\
\"extra.stuff\": false,\
@ -41,7 +44,7 @@ fn test_get_set_reset_extend() {
PREFS.reset("shell.homepage");
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://servo.org".to_owned()));
let extension = read_prefs_from_file(json_str.as_bytes()).unwrap();
let extension = read_prefs(json_str).unwrap();
PREFS.extend(extension);
assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://google.com".to_owned()));
assert_eq!(*PREFS.get("layout.writing-mode.enabled"), PrefValue::Boolean(true));

View file

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

View file

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

View file

@ -2,18 +2,17 @@
* 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 embedder_traits::resources;
use gaol::profile::{Operation, PathPattern, Profile};
use servo_config::resource_files;
use std::path::PathBuf;
/// Our content process sandbox profile on Mac. As restrictive as possible.
#[cfg(target_os = "macos")]
pub fn content_process_sandbox_profile() -> Profile {
use gaol::platform;
Profile::new(vec![
let mut operations = vec![
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("/System/Library/Fonts"))),
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from(
@ -27,16 +26,32 @@ pub fn content_process_sandbox_profile() -> Profile {
Operation::SystemInfoRead,
Operation::PlatformSpecific(platform::macos::Operation::MachLookup(
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.
#[cfg(not(target_os = "macos"))]
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::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]
app_units = "0.6"
atomic_refcell = "0.1"
embedder_traits = {path = "../embedder_traits"}
euclid = "0.17"
fnv = "1.0"
gfx = {path = "../gfx"}

View file

@ -9,6 +9,7 @@
extern crate app_units;
extern crate atomic_refcell;
extern crate embedder_traits;
extern crate euclid;
extern crate fnv;
extern crate gfx;
@ -55,6 +56,7 @@ mod dom_wrapper;
use app_units::Au;
use dom_wrapper::{ServoLayoutElement, ServoLayoutDocument, ServoLayoutNode};
use dom_wrapper::drop_style_and_layout_data;
use embedder_traits::resources::{self, Resource};
use euclid::{Point2D, Rect, Size2D, TypedScale, TypedSize2D};
use fnv::FnvHashMap;
use gfx::display_list::{OpaqueNode, WebRenderImageInfo};
@ -110,7 +112,6 @@ use servo_arc::Arc as ServoArc;
use servo_atoms::Atom;
use servo_config::opts;
use servo_config::prefs::PREFS;
use servo_config::resource_files::read_resource_file;
use servo_geometry::MaxRect;
use servo_url::ServoUrl;
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 parse_ua_stylesheet(
shared_lock: &SharedRwLock,
filename: &'static str,
filename: &str,
content: &[u8],
) -> Result<DocumentStyleSheet, &'static str> {
let res = read_resource_file(filename).map_err(|_| filename)?;
Ok(DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes(
&res,
content,
ServoUrl::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
None,
None,
@ -1758,12 +1759,17 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
}
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.
// (Does it make a difference?)
for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] {
user_or_user_agent_stylesheets.push(parse_ua_stylesheet(&shared_lock, filename)?);
}
let mut user_or_user_agent_stylesheets = vec![
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 {
user_or_user_agent_stylesheets.push(
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 {
shared_lock: shared_lock,

View file

@ -16,6 +16,7 @@ base64 = "0.6"
brotli = "1.0.6"
cookie = "0.10"
devtools_traits = {path = "../devtools_traits"}
embedder_traits = { path = "../embedder_traits" }
flate2 = "1"
hyper = "0.10"
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 openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3};
use openssl::ssl::{SslConnectorBuilder, SslMethod};
use openssl::x509;
use std::io;
use std::net::TcpStream;
use std::path::PathBuf;
pub struct HttpsConnector {
ssl: OpensslClient,
@ -50,9 +50,33 @@ impl NetworkConnector for 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();
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_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);
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
* 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::pub_domains::reg_suffix;
use serde_json;
use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl;
use std::collections::HashMap;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::from_utf8;
use time;
#[derive(Clone, Deserialize, Serialize)]
@ -64,15 +63,13 @@ impl HstsList {
}
/// 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)]
struct HstsEntries {
entries: Vec<HstsEntry>,
}
let hsts_entries: Option<HstsEntries> = from_utf8(&preload_content)
.ok()
.and_then(|c| serde_json::from_str(c).ok());
let hsts_entries: Option<HstsEntries> = serde_json::from_str(preload_content).ok();
hsts_entries.map_or(None, |hsts_entries| {
let mut hsts_list: HstsList = HstsList::new();
@ -86,10 +83,8 @@ impl HstsList {
}
pub fn from_servo_preload() -> HstsList {
let file_bytes = read_resource_file("hsts_preload.json")
.expect("Could not find Servo HSTS preload file");
HstsList::from_preload(&file_bytes)
.expect("Servo HSTS preload file is invalid")
let list = resources::read_string(Resource::HstsPreloadList);
HstsList::from_preload(&list).expect("Servo HSTS preload file is invalid")
}
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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use immeta::load_from_buf;
use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError};
use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memory};
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageResponder};
use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState};
use net_traits::image_cache::{PendingImageId, UsePlaceholder};
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fs::File;
use std::io::{self, Read};
use std::io;
use std::mem;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::thread;
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>> {
let mut file = File::open(path)?;
let mut image_data = vec![];
file.read_to_end(&mut image_data)?;
let mut image = load_from_memory(&image_data).unwrap();
fn get_placeholder_image(webrender_api: &webrender_api::RenderApi, data: &[u8]) -> io::Result<Arc<Image>> {
let mut image = load_from_memory(&data).unwrap();
set_webrender_image_key(webrender_api, &mut image);
Ok(Arc::new(image))
}
@ -403,15 +398,14 @@ impl ImageCache for ImageCacheImpl {
fn new(webrender_api: webrender_api::RenderApi) -> ImageCacheImpl {
debug!("New image cache");
let mut placeholder_path = resources_dir_path().expect("Can't figure out resources path.");
placeholder_path.push("rippy.png");
let rippy_data = resources::read_bytes(Resource::RippyPNG);
ImageCacheImpl {
store: Arc::new(Mutex::new(ImageCacheStore {
pending_loads: AllPendingLoads::new(),
completed_loads: HashMap::new(),
placeholder_image: get_placeholder_image(&webrender_api, &placeholder_path).ok(),
placeholder_url: ServoUrl::from_file_path(&placeholder_path).unwrap(),
placeholder_image: get_placeholder_image(&webrender_api, &rippy_data).ok(),
placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(),
webrender_api: webrender_api,
}))
}

View file

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

View file

@ -8,6 +8,7 @@ use cookie;
use cookie_rs;
use cookie_storage::CookieStorage;
use devtools_traits::DevtoolsControlMsg;
use embedder_traits::resources::{self, Resource};
use fetch::cors_cache::CorsCache;
use fetch::methods::{CancellationListener, FetchContext, fetch};
use filemanager_thread::{FileManager, TFDProvider};
@ -31,12 +32,11 @@ use serde::{Deserialize, Serialize};
use serde_json;
use servo_allocator;
use servo_config::opts;
use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl;
use std::borrow::{Cow, ToOwned};
use std::collections::HashMap;
use std::error::Error;
use std::fs::File;
use std::fs::{self, File};
use std::io::prelude::*;
use std::ops::Deref;
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");
}
let ca_file = match opts::get().certificate_path {
Some(ref path) => PathBuf::from(path),
None => resources_dir_path()
.expect("Need certificate file to make network requests")
.join("certs"),
let certs = match opts::get().certificate_path {
Some(ref path) => {
fs::read_to_string(path).expect("Couldn't not find certificate file")
}
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 {
cookie_jar: RwLock::new(cookie_jar),
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),
};
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);
(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/. */
use cookie_rs;
use embedder_traits::resources::register_resources_for_tests;
use hyper::header::{Header, SetCookie};
use net::cookie::Cookie;
use net::cookie_storage::CookieStorage;
@ -56,6 +57,7 @@ fn test_default_path() {
#[test]
fn fn_cookie_constructor() {
use net_traits::CookieSource;
register_resources_for_tests();
let url = &ServoUrl::parse("http://example.com/foo").unwrap();
@ -102,6 +104,7 @@ fn fn_cookie_constructor() {
#[test]
fn test_cookie_secure_prefix() {
register_resources_for_tests();
let url = &ServoUrl::parse("https://example.com").unwrap();
let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345").unwrap();
assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
@ -129,6 +132,7 @@ fn test_cookie_secure_prefix() {
#[test]
fn test_cookie_host_prefix() {
register_resources_for_tests();
let url = &ServoUrl::parse("https://example.com").unwrap();
let cookie = cookie_rs::Cookie::parse("__Host-SID=12345").unwrap();
assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
@ -182,6 +186,7 @@ fn delay_to_ensure_different_timestamp() {}
#[test]
fn test_sort_order() {
use std::cmp::Ordering;
register_resources_for_tests();
let url = &ServoUrl::parse("http://example.com/foo").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)
{
register_resources_for_tests();
let source = CookieSource::HTTP;
let cookie = cookie_rs::Cookie::parse(cookie_str.to_owned()).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]
fn test_insecure_cookies_cannot_evict_secure_cookie() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5);
let secure_url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::HTTP;
@ -245,6 +252,7 @@ fn test_insecure_cookies_cannot_evict_secure_cookie() {
#[test]
fn test_secure_cookies_eviction() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5);
let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::HTTP;
@ -280,6 +288,7 @@ fn test_secure_cookies_eviction() {
#[test]
fn test_secure_cookies_eviction_non_http_source() {
register_resources_for_tests();
let mut storage = CookieStorage::new(5);
let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
let source = CookieSource::NonHTTP;
@ -341,6 +350,7 @@ fn add_retrieve_cookies(set_location: &str,
#[test]
fn test_cookie_eviction_expired() {
register_resources_for_tests();
let mut vec = Vec::new();
for i in 1..6 {
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]
fn test_cookie_eviction_all_secure_one_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new();
for i in 1..5 {
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]
fn test_cookie_eviction_all_secure_new_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new();
for i in 1..6 {
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]
fn test_cookie_eviction_all_nonsecure_new_secure() {
register_resources_for_tests();
let mut vec = Vec::new();
for i in 1..6 {
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]
fn test_cookie_eviction_all_nonsecure_new_nonsecure() {
register_resources_for_tests();
let mut vec = Vec::new();
for i in 1..6 {
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::HttpRequest as DevtoolsHttpRequest;
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
use embedder_traits::resources::register_resources_for_tests;
use fetch_with_context;
use fetch_with_cors_cache;
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::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
use servo_config::resource_files::resources_dir_path;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Sender, channel};
@ -48,6 +49,7 @@ use unicase::UniCase;
#[test]
fn test_fetch_response_is_not_network_error() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -67,6 +69,7 @@ fn test_fetch_response_is_not_network_error() {
#[test]
fn test_fetch_on_bad_port_is_network_error() {
register_resources_for_tests();
let url = ServoUrl::parse("http://www.example.org:6667").unwrap();
let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None);
@ -79,6 +82,7 @@ fn test_fetch_on_bad_port_is_network_error() {
#[test]
fn test_fetch_response_body_matches_const_message() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"Hello World!";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -104,6 +108,7 @@ fn test_fetch_response_body_matches_const_message() {
#[test]
fn test_fetch_aboutblank() {
register_resources_for_tests();
let url = ServoUrl::parse("about:blank").unwrap();
let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None);
@ -115,6 +120,7 @@ fn test_fetch_aboutblank() {
#[test]
fn test_fetch_blob() {
register_resources_for_tests();
use ipc_channel::ipc;
use net_traits::blob_url_store::BlobBuf;
@ -155,9 +161,8 @@ fn test_fetch_blob() {
#[test]
fn test_fetch_file() {
let mut path = resources_dir_path().expect("Cannot find resource dir");
path.push("servo.css");
register_resources_for_tests();
let path = Path::new("../../resources/servo.css").canonicalize().unwrap();
let url = ServoUrl::from_file_path(path.clone()).unwrap();
let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None);
@ -183,6 +188,7 @@ fn test_fetch_file() {
#[test]
fn test_fetch_ftp() {
register_resources_for_tests();
let url = ServoUrl::parse("ftp://not-supported").unwrap();
let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None);
@ -193,6 +199,7 @@ fn test_fetch_ftp() {
#[test]
fn test_fetch_bogus_scheme() {
register_resources_for_tests();
let url = ServoUrl::parse("bogus://whatever").unwrap();
let origin = Origin::Origin(url.origin());
let mut request = Request::new(url, Some(origin), None);
@ -203,6 +210,7 @@ fn test_fetch_bogus_scheme() {
#[test]
fn test_cors_preflight_fetch() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0));
let handler = move |request: HyperRequest, mut response: HyperResponse| {
@ -240,6 +248,7 @@ fn test_cors_preflight_fetch() {
#[test]
fn test_cors_preflight_cache_fetch() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0));
let counter = state.clone();
@ -292,6 +301,7 @@ fn test_cors_preflight_cache_fetch() {
#[test]
fn test_cors_preflight_fetch_network_error() {
register_resources_for_tests();
static ACK: &'static [u8] = b"ACK";
let state = Arc::new(AtomicUsize::new(0));
let handler = move |request: HyperRequest, mut response: HyperResponse| {
@ -322,6 +332,7 @@ fn test_cors_preflight_fetch_network_error() {
#[test]
fn test_fetch_response_is_basic_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, mut response: HyperResponse| {
response.headers_mut().set(SetCookie(vec![]));
@ -348,6 +359,7 @@ fn test_fetch_response_is_basic_filtered() {
#[test]
fn test_fetch_response_is_cors_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, mut response: HyperResponse| {
// this is mandatory for the Cors Check to pass
@ -402,6 +414,7 @@ fn test_fetch_response_is_cors_filtered() {
#[test]
fn test_fetch_response_is_opaque_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -435,6 +448,7 @@ fn test_fetch_response_is_opaque_filtered() {
#[test]
fn test_fetch_response_is_opaque_redirect_filtered() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri {
@ -481,6 +495,7 @@ fn test_fetch_response_is_opaque_redirect_filtered() {
#[test]
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.
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.
#[test]
fn test_fetch_with_hsts() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
};
let path = resources_dir_path().expect("Cannot find resource dir");
let mut cert_path = path.clone();
cert_path.push("self_signed_certificate_for_testing.crt");
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt").canonicalize().unwrap();
let key_path = Path::new("../../resources/privatekey_for_testing.key").canonicalize().unwrap();
let mut key_path = path.clone();
key_path.push("privatekey_for_testing.key");
let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path)
let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path.clone())
.unwrap();
//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 ca_file = resources_dir_path().unwrap().join("self_signed_certificate_for_testing.crt");
let ssl_client = create_ssl_client(&ca_file);
let mut ca_content = String::new();
File::open(cert_path).unwrap().read_to_string(&mut ca_content).unwrap();
let ssl_client = create_ssl_client(&ca_content);
let context = FetchContext {
state: Arc::new(HttpState::new(ssl_client)),
@ -568,6 +581,7 @@ fn test_fetch_with_hsts() {
#[test]
fn test_fetch_with_sri_network_error() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -592,6 +606,7 @@ fn test_fetch_with_sri_network_error() {
#[test]
fn test_fetch_with_sri_sucess() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"alert('Hello, world.');";
let handler = move |_: HyperRequest, response: HyperResponse| {
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 {
register_resources_for_tests();
let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri {
RequestUri::AbsolutePath(url) =>
@ -689,6 +705,7 @@ fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response
#[test]
fn test_fetch_redirect_count_ceiling() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"no more redirects";
// how many redirects to cause
let redirect_cap = 20;
@ -708,6 +725,7 @@ fn test_fetch_redirect_count_ceiling() {
#[test]
fn test_fetch_redirect_count_failure() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"this message shouldn't be reachable";
// how many redirects to cause
let redirect_cap = 21;
@ -773,6 +791,7 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender<bool>, status_code: Stat
#[test]
fn test_fetch_redirect_updates_method() {
register_resources_for_tests();
let (tx, rx) = channel();
test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, Method::Post);
@ -831,6 +850,7 @@ fn response_is_done(response: &Response) -> bool {
#[test]
fn test_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"this message should be retrieved in full";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -849,6 +869,7 @@ fn test_fetch_async_returns_complete_response() {
#[test]
fn test_opaque_filtered_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();
@ -870,6 +891,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() {
#[test]
fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"";
let handler = move |request: HyperRequest, mut response: HyperResponse| {
let redirects = match request.uri {
@ -906,6 +928,7 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
#[test]
fn test_fetch_with_devtools() {
register_resources_for_tests();
static MESSAGE: &'static [u8] = b"Yay!";
let handler = move |_: HyperRequest, response: HyperResponse| {
response.send(MESSAGE).unwrap();

View file

@ -176,24 +176,24 @@ fn test_push_entry_to_hsts_list_should_add_an_entry() {
#[test]
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")
}
#[test]
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")
}
#[test]
fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() {
let mock_preload_content = b"{\
\"entries\": [\
{\"host\": \"mozilla.org\",\
\"include_subdomains\": false}\
]\
}";
let mock_preload_content = "{\
\"entries\": [\
{\"host\": \"mozilla.org\",\
\"include_subdomains\": false}\
]\
}";
let hsts_list = HstsList::from_preload(mock_preload_content);
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::HttpRequest as DevtoolsHttpRequest;
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
use embedder_traits::resources::register_resources_for_tests;
use fetch;
use fetch_with_context;
use flate2::Compression;
@ -312,6 +313,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
#[test]
fn test_redirected_request_to_devtools() {
register_resources_for_tests();
let post_handler = move |request: HyperRequest, response: HyperResponse| {
assert_eq!(request.method, Method::Get);
response.send(b"Yay!").unwrap();

View file

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

View file

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

View file

@ -6,6 +6,7 @@
#![deny(unsafe_code)]
extern crate cookie as cookie_rs;
extern crate embedder_traits;
extern crate hyper;
extern crate hyper_serde;
extern crate image as piston_image;
@ -18,7 +19,6 @@ extern crate msg;
extern crate num_traits;
#[macro_use] extern crate serde;
extern crate servo_arc;
extern crate servo_config;
extern crate servo_url;
extern crate url;
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
//! 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 std::collections::HashSet;
use std::iter::FromIterator;
use std::str::from_utf8;
#[derive(Clone, Debug)]
pub struct PubDomainRules {
@ -121,9 +120,7 @@ impl PubDomainRules {
}
fn load_pub_domains() -> PubDomainRules {
let content = read_resource_file("public_domains.txt").expect("Could not find public suffix list file");
let content = from_utf8(&content).expect("Could not read public suffix list file");
PubDomainRules::parse(content)
PubDomainRules::parse(&resources::read_string(Resource::DomainList))
}
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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate embedder_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};
// These tests may need to be updated if the PSL changes.
#[test]
fn test_is_pub_domain_plain() {
register_resources_for_tests();
assert!(is_pub_domain("com"));
assert!(is_pub_domain(".org"));
assert!(is_pub_domain("za.org"));
@ -19,6 +22,7 @@ fn test_is_pub_domain_plain() {
#[test]
fn test_is_pub_domain_wildcard() {
register_resources_for_tests();
assert!(is_pub_domain("hello.bd"));
assert!(is_pub_domain("world.jm"));
assert!(is_pub_domain("toto.kobe.jp"));
@ -26,6 +30,7 @@ fn test_is_pub_domain_wildcard() {
#[test]
fn test_is_pub_domain_exception() {
register_resources_for_tests();
assert_eq!(is_pub_domain("www.ck"), false);
assert_eq!(is_pub_domain("city.kawasaki.jp"), false);
assert_eq!(is_pub_domain("city.nagoya.jp"), false);
@ -34,6 +39,7 @@ fn test_is_pub_domain_exception() {
#[test]
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);
@ -46,6 +52,7 @@ fn test_is_pub_domain_not() {
#[test]
fn test_is_pub_domain() {
register_resources_for_tests();
assert!(!is_pub_domain("city.yokohama.jp"));
assert!(!is_pub_domain("foo.bar.baz.yokohama.jp"));
assert!(!is_pub_domain("foo.bar.city.yokohama.jp"));
@ -64,6 +71,7 @@ fn test_is_pub_domain() {
#[test]
fn test_is_reg_domain() {
register_resources_for_tests();
assert!(!is_reg_domain("com"));
assert!(!is_reg_domain("foo.bar.baz.yokohama.jp"));
assert!(!is_reg_domain("foo.bar.com"));
@ -81,6 +89,7 @@ fn test_is_reg_domain() {
#[test]
fn test_pub_suffix() {
register_resources_for_tests();
assert_eq!(pub_suffix("city.yokohama.jp"), "yokohama.jp");
assert_eq!(pub_suffix("com"), "com");
assert_eq!(pub_suffix("foo.bar.baz.yokohama.jp"), "baz.yokohama.jp");
@ -98,6 +107,7 @@ fn test_pub_suffix() {
#[test]
fn test_reg_suffix() {
register_resources_for_tests();
assert_eq!(reg_suffix("city.yokohama.jp"), "city.yokohama.jp");
assert_eq!(reg_suffix("com"), "com");
assert_eq!(reg_suffix("foo.bar.baz.yokohama.jp"), "bar.baz.yokohama.jp");
@ -115,6 +125,7 @@ fn test_reg_suffix() {
#[test]
fn test_weirdness() {
register_resources_for_tests();
// 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!(!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"}
dom_struct = {path = "../dom_struct"}
domobject_derive = {path = "../domobject_derive"}
embedder_traits = {path = "../embedder_traits"}
encoding_rs = "0.7"
euclid = "0.17"
fnv = "1.0"

View file

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

View file

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

View file

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

View file

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

View file

@ -33,6 +33,7 @@ pub extern crate constellation;
pub extern crate debugger;
pub extern crate devtools;
pub extern crate devtools_traits;
pub extern crate embedder_traits;
pub extern crate euclid;
pub extern crate gfx;
pub extern crate ipc_channel;
@ -95,7 +96,6 @@ use profile_traits::time;
use script_traits::{ConstellationMsg, SWManagerSenders, ScriptToConstellationChan};
use servo_config::opts;
use servo_config::prefs::PREFS;
use servo_config::resource_files::resources_dir_path;
use std::borrow::Cow;
use std::cmp::max;
use std::path::PathBuf;
@ -154,9 +154,6 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
devtools::start_server(port)
});
let mut resource_path = resources_dir_path().unwrap();
resource_path.push("shaders");
let coordinates = window.get_coordinates();
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 {
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,
debug_flags: debug_flags,
recorder: recorder,

View file

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

View file

@ -25,6 +25,8 @@ extern crate euclid;
#[cfg(target_os = "windows")] extern crate gdi32;
extern crate gleam;
extern crate glutin;
#[cfg(not(target_os = "android"))]
#[macro_use] extern crate lazy_static;
// The window backed by glutin
#[macro_use] extern crate log;
#[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;
mod glutin_app;
mod resources;
use backtrace::Backtrace;
use servo::Servo;
@ -99,14 +102,16 @@ fn install_crash_handler() {}
fn main() {
install_crash_handler();
resources::init();
// Parse the command line options and store them globally
let opts_result = opts::from_cmdline_args(&*args());
let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
Some(token)
} else {
if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
::std::env::set_var("RUST_LOG", "compositing::constellation");
if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "compositing::constellation");
}
None
@ -217,7 +222,7 @@ fn main() {
#[cfg(target_os = "android")]
fn setup_logging() {
// 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() };
}
@ -263,7 +268,6 @@ fn args() -> Vec<String> {
#[cfg(not(target_os = "android"))]
fn args() -> Vec<String> {
use std::env;
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>
</head>
<body>
<img src="chrome://resources/itried.jpg">
<p>${reason}</p>
</body>
</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
public void onCreate(Bundle savedInstanceState) {
try {
extractAssets();
} catch (IOException e) {
throw new RuntimeException(e);
}
final Intent intent = getIntent();
if (intent != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
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() {
File file = getExternalFilesDir(null);
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) {
try {

View file

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

View file

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

View file

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