diff options
Diffstat (limited to 'components/util')
-rw-r--r-- | components/util/Cargo.toml | 37 | ||||
-rw-r--r-- | components/util/basedir.rs | 72 | ||||
-rw-r--r-- | components/util/geometry.rs | 50 | ||||
-rw-r--r-- | components/util/lib.rs | 54 | ||||
-rw-r--r-- | components/util/opts.rs | 958 | ||||
-rw-r--r-- | components/util/prefs.rs | 262 | ||||
-rw-r--r-- | components/util/remutex.rs | 234 | ||||
-rw-r--r-- | components/util/resource_files.rs | 67 | ||||
-rw-r--r-- | components/util/thread.rs | 11 |
9 files changed, 0 insertions, 1745 deletions
diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml deleted file mode 100644 index 2f9ee4486cf..00000000000 --- a/components/util/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "util" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "util" -path = "lib.rs" - -[features] -# servo as opposed to geckolib -servo = ["serde", "serde_derive", "app_units/plugins", - "euclid/unstable", "url/heap_size", "url/serde", "plugins"] - -[dependencies] -app_units = "0.3" -bitflags = "0.7" -euclid = "0.10.1" -getopts = "0.2.11" -heapsize = "0.3.0" -lazy_static = "0.2" -log = "0.3.5" -num_cpus = "1.1.0" -rustc-serialize = "0.3" -serde = {version = "0.8", optional = true} -serde_derive = {version = "0.8", optional = true} -servo_url = {path = "../url"} -plugins = {path = "../plugins", optional = true} -url = "1.2" - -[dev-dependencies] -env_logger = "0.3" - -[target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))'.dependencies] -xdg = "2.0" diff --git a/components/util/basedir.rs b/components/util/basedir.rs deleted file mode 100644 index 5c7896a388b..00000000000 --- a/components/util/basedir.rs +++ /dev/null @@ -1,72 +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/. */ - -//! Contains routines for retrieving default config directories. -//! For linux based platforms, it uses the XDG base directory spec but provides -//! similar abstractions for non-linux platforms. - -#[cfg(any(target_os = "macos", target_os = "windows"))] -use std::env; -use std::path::PathBuf; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -use xdg; - -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -pub fn default_config_dir() -> Option<PathBuf> { - let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); - let config_dir = xdg_dirs.get_config_home(); - Some(config_dir) -} - -#[cfg(target_os = "android")] -pub fn default_config_dir() -> Option<PathBuf> { - Some(PathBuf::from("/sdcard/servo")) -} - -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -pub fn default_data_dir() -> Option<PathBuf> { - let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); - let data_dir = xdg_dirs.get_data_home(); - Some(data_dir) -} - -#[cfg(target_os = "android")] -pub fn default_data_dir() -> Option<PathBuf> { - Some(PathBuf::from("/sdcard/servo")) -} - -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -pub fn default_cache_dir() -> Option<PathBuf> { - let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); - let cache_dir = xdg_dirs.get_cache_home(); - Some(cache_dir) -} - -#[cfg(target_os = "android")] -pub fn default_cache_dir() -> Option<PathBuf> { - Some(PathBuf::from("/sdcard/servo")) -} - -#[cfg(target_os = "macos")] -pub fn default_config_dir() -> Option<PathBuf> { - let mut config_dir = env::home_dir().unwrap(); - config_dir.push("Library"); - config_dir.push("Application Support"); - config_dir.push("Servo"); - Some(config_dir) -} - -#[cfg(target_os = "windows")] -pub fn default_config_dir() -> Option<PathBuf> { - let mut config_dir = match env::var("APPDATA") { - Ok(appdata_path) => PathBuf::from(appdata_path), - Err(_) => { let mut dir = env::home_dir().unwrap(); - dir.push("Appdata"); - dir.push("Roaming"); - dir - } - }; - config_dir.push("Servo"); - Some(config_dir) -} diff --git a/components/util/geometry.rs b/components/util/geometry.rs deleted file mode 100644 index 2d102d2d0dc..00000000000 --- a/components/util/geometry.rs +++ /dev/null @@ -1,50 +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 app_units::{Au, MAX_AU}; -use euclid::point::Point2D; -use euclid::rect::Rect; -use euclid::size::Size2D; -use std::i32; - -// Units for use with euclid::length and euclid::scale_factor. - -/// A normalized "pixel" at the default resolution for the display. -/// -/// Like the CSS "px" unit, the exact physical size of this unit may vary between devices, but it -/// should approximate a device-independent reference length. This unit corresponds to Android's -/// "density-independent pixel" (dip), Mac OS X's "point", and Windows "device-independent pixel." -/// -/// The relationship between DevicePixel and ScreenPx is defined by the OS. On most low-dpi -/// screens, one ScreenPx is equal to one DevicePixel. But on high-density screens it can be -/// some larger number. For example, by default on Apple "retina" displays, one ScreenPx equals -/// two DevicePixels. On Android "MDPI" displays, one ScreenPx equals 1.5 device pixels. -/// -/// The ratio between ScreenPx and DevicePixel for a given display be found by calling -/// `servo::windowing::WindowMethods::hidpi_factor`. -#[derive(Clone, Copy, Debug)] -pub enum ScreenPx {} - -known_heap_size!(0, ScreenPx); - -// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was -// originally proposed in 2002 as a standard unit of measure in Gecko. -// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info. - -#[inline(always)] -pub fn max_rect() -> Rect<Au> { - Rect::new(Point2D::new(Au(i32::MIN / 2), Au(i32::MIN / 2)), Size2D::new(MAX_AU, MAX_AU)) -} - -/// A helper function to convert a rect of `f32` pixels to a rect of app units. -pub fn f32_rect_to_au_rect(rect: Rect<f32>) -> Rect<Au> { - Rect::new(Point2D::new(Au::from_f32_px(rect.origin.x), Au::from_f32_px(rect.origin.y)), - Size2D::new(Au::from_f32_px(rect.size.width), Au::from_f32_px(rect.size.height))) -} - -/// A helper function to convert a rect of `Au` pixels to a rect of f32 units. -pub fn au_rect_to_f32_rect(rect: Rect<Au>) -> Rect<f32> { - Rect::new(Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px()), - Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px())) -} diff --git a/components/util/lib.rs b/components/util/lib.rs deleted file mode 100644 index 3c72d90d257..00000000000 --- a/components/util/lib.rs +++ /dev/null @@ -1,54 +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_attr(feature = "servo", feature(nonzero))] -#![cfg_attr(feature = "servo", feature(plugin))] -#![cfg_attr(feature = "servo", feature(proc_macro))] -#![cfg_attr(feature = "servo", plugin(plugins))] - -#![deny(unsafe_code)] - -extern crate app_units; -#[allow(unused_extern_crates)] #[macro_use] extern crate bitflags; -extern crate core; -#[macro_use] extern crate euclid; -extern crate getopts; -#[macro_use] extern crate heapsize; -#[allow(unused_extern_crates)] #[macro_use] extern crate lazy_static; -#[macro_use] extern crate log; -extern crate num_cpus; -extern crate rustc_serialize; -#[cfg(feature = "servo")] extern crate serde; -#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive; -extern crate servo_url; -extern crate url; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -extern crate xdg; - -pub mod basedir; -pub mod geometry; -#[allow(unsafe_code)] pub mod opts; -pub mod prefs; -#[cfg(feature = "servo")] pub mod remutex; -pub mod resource_files; -pub mod thread; - -pub fn servo_version() -> String { - let cargo_version = env!("CARGO_PKG_VERSION"); - let git_info = option_env!("GIT_INFO"); - match git_info { - Some(info) => format!("Servo {}{}", cargo_version, info), - None => format!("Servo {}", cargo_version), - } -} - -pub fn clamp<T: Ord>(lo: T, mid: T, hi: T) -> T { - if mid < lo { - lo - } else if mid > hi { - hi - } else { - mid - } -} diff --git a/components/util/opts.rs b/components/util/opts.rs deleted file mode 100644 index 4f1db5d8c50..00000000000 --- a/components/util/opts.rs +++ /dev/null @@ -1,958 +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/. */ - -//! Configuration options for a single run of the servo application. Created -//! from command line arguments. - -use euclid::size::TypedSize2D; -use geometry::ScreenPx; -use getopts::Options; -use num_cpus; -use prefs::{self, PrefValue, PREFS}; -use resource_files::set_resources_path; -use servo_url::ServoUrl; -use std::borrow::Cow; -use std::cmp; -use std::default::Default; -use std::env; -use std::fs::{self, File}; -use std::io::{self, Read, Write}; -use std::path::{Path, PathBuf}; -use std::process; -use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; -use url::{self, Url}; - - -/// Global flags for Servo, currently set on the command line. -#[derive(Clone)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub struct Opts { - pub is_running_problem_test: bool, - - /// The initial URL to load. - pub url: Option<ServoUrl>, - - /// How many threads to use for CPU painting (`-t`). - /// - /// Note that painting is sequentialized when using GPU painting. - pub paint_threads: usize, - - /// The maximum size of each tile in pixels (`-s`). - pub tile_size: usize, - - /// The ratio of device pixels per px at the default scale. If unspecified, will use the - /// platform default setting. - pub device_pixels_per_px: Option<f32>, - - /// `None` to disable the time profiler or `Some` with an interval in seconds to enable it and - /// cause it to produce output on that interval (`-p`). - pub time_profiling: Option<OutputOptions>, - - /// When the profiler is enabled, this is an optional path to dump a self-contained HTML file - /// visualizing the traces as a timeline. - pub time_profiler_trace_path: Option<String>, - - /// `None` to disable the memory profiler or `Some` with an interval in seconds to enable it - /// and cause it to produce output on that interval (`-m`). - pub mem_profiler_period: Option<f64>, - - pub nonincremental_layout: bool, - - /// Where to load userscripts from, if any. An empty string will load from - /// the resources/user-agent-js directory, and if the option isn't passed userscripts - /// won't be loaded - pub userscripts: Option<String>, - - pub user_stylesheets: Vec<(Vec<u8>, ServoUrl)>, - - pub output_file: Option<String>, - - /// Replace unpaires surrogates in DOM strings with U+FFFD. - /// See https://github.com/servo/servo/issues/6564 - pub replace_surrogates: bool, - - /// Log GC passes and their durations. - pub gc_profile: bool, - - /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. - pub load_webfonts_synchronously: bool, - - pub headless: bool, - pub hard_fail: bool, - - /// True if we should bubble intrinsic widths sequentially (`-b`). If this is true, then - /// intrinsic widths are computed as a separate pass instead of during flow construction. You - /// may wish to turn this flag on in order to benchmark style recalculation against other - /// browser engines. - pub bubble_inline_sizes_separately: bool, - - /// True if we should show borders on all layers and tiles for - /// debugging purposes (`--show-debug-borders`). - pub show_debug_borders: bool, - - /// True if we should show borders on all fragments for debugging purposes - /// (`--show-debug-fragment-borders`). - pub show_debug_fragment_borders: bool, - - /// True if we should paint tiles with overlays based on which thread painted them. - pub show_debug_parallel_paint: bool, - - /// True if we should paint borders around flows based on which thread painted them. - pub show_debug_parallel_layout: bool, - - /// True if we should paint tiles a random color whenever they're repainted. Useful for - /// debugging invalidation. - pub paint_flashing: bool, - - /// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests - /// where pixel perfect results are required when using fonts such as the Ahem - /// font for layout tests. - pub enable_text_antialiasing: bool, - - /// If set with --enable-subpixel, use subpixel antialiasing for glyphs. In the future - /// this will likely become the default, but for now it's opt-in while we work - /// out any bugs and improve the implementation. - pub enable_subpixel_text_antialiasing: bool, - - /// If set with --disable-canvas-aa, disable antialiasing on the HTML canvas element. - /// Like --disable-text-aa, this is useful for reftests where pixel perfect results are required. - pub enable_canvas_antialiasing: bool, - - /// True if each step of layout is traced to an external JSON file - /// for debugging purposes. Settings this implies sequential layout - /// and paint. - pub trace_layout: bool, - - /// Periodically print out on which events script threads spend their processing time. - pub profile_script_events: bool, - - /// Enable all heartbeats for profiling. - pub profile_heartbeats: bool, - - /// `None` to disable debugger or `Some` with a port number to start a server to listen to - /// remote Firefox debugger connections. - pub debugger_port: Option<u16>, - - /// `None` to disable devtools or `Some` with a port number to start a server to listen to - /// remote Firefox devtools connections. - pub devtools_port: Option<u16>, - - /// `None` to disable WebDriver or `Some` with a port number to start a server to listen to - /// remote WebDriver commands. - pub webdriver_port: Option<u16>, - - /// The initial requested size of the window. - pub initial_window_size: TypedSize2D<u32, ScreenPx>, - - /// An optional string allowing the user agent to be set for testing. - pub user_agent: Cow<'static, str>, - - /// Whether we're running in multiprocess mode. - pub multiprocess: bool, - - /// Whether we're running inside the sandbox. - pub sandbox: bool, - - /// Probability of randomly closing a pipeline, - /// used for testing the hardening of the constellation. - pub random_pipeline_closure_probability: Option<f32>, - - /// The seed for the RNG used to randomly close pipelines, - /// used for testing the hardening of the constellation. - pub random_pipeline_closure_seed: Option<usize>, - - /// Dumps the DOM after restyle. - pub dump_style_tree: bool, - - /// Dumps the rule tree. - pub dump_rule_tree: bool, - - /// Dumps the flow tree after a layout. - pub dump_flow_tree: bool, - - /// Dumps the display list after a layout. - pub dump_display_list: bool, - - /// Dumps the display list in JSON form after a layout. - pub dump_display_list_json: bool, - - /// Dumps the layer tree when it changes. - pub dump_layer_tree: bool, - - /// Emits notifications when there is a relayout. - pub relayout_event: bool, - - /// Whether Style Sharing Cache is used - pub disable_share_style_cache: bool, - - /// Whether to show in stdout style sharing cache stats after a restyle. - pub style_sharing_stats: bool, - - /// Translate mouse input into touch events. - pub convert_mouse_to_touch: bool, - - /// True to exit after the page load (`-x`). - pub exit_after_load: bool, - - /// Do not use native titlebar - pub no_native_titlebar: bool, - - /// Enable vsync in the compositor - pub enable_vsync: bool, - - /// True to show webrender profiling stats on screen. - pub webrender_stats: bool, - - /// True to show webrender debug on screen. - pub webrender_debug: bool, - - /// True if webrender recording should be enabled. - pub webrender_record: bool, - - /// 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. - pub precache_shaders: bool, - - /// True if WebRender should use multisample antialiasing. - pub use_msaa: bool, - - /// Directory for a default config directory - pub config_dir: Option<PathBuf>, - - // don't skip any backtraces on panic - pub full_backtraces: bool, - - /// True to use OS native signposting facilities. This makes profiling events (script activity, - /// reflow, compositing, etc.) appear in Instruments.app on macOS. - pub signpost: bool, - - /// Print the version and exit. - pub is_printing_version: bool, -} - -fn print_usage(app: &str, opts: &Options) { - let message = format!("Usage: {} [ options ... ] [URL]\n\twhere options include", app); - println!("{}", opts.usage(&message)); -} - - -/// Debug options for Servo, currently set on the command line with -Z -#[derive(Default)] -pub struct DebugOptions { - /// List all the debug options. - pub help: bool, - - /// Bubble intrinsic widths separately like other engines. - pub bubble_widths: bool, - - /// Disable antialiasing of rendered text. - pub disable_text_aa: bool, - - /// Enable subpixel antialiasing of rendered text. - pub enable_subpixel_aa: bool, - - /// Disable antialiasing of rendered text on the HTML canvas element. - pub disable_canvas_aa: bool, - - /// Print the DOM after each restyle. - pub dump_style_tree: bool, - - /// Dumps the rule tree. - pub dump_rule_tree: bool, - - /// Print the flow tree after each layout. - pub dump_flow_tree: bool, - - /// Print the display list after each layout. - pub dump_display_list: bool, - - /// Print the display list in JSON form. - pub dump_display_list_json: bool, - - /// Print the layer tree whenever it changes. - pub dump_layer_tree: bool, - - /// Print notifications when there is a relayout. - pub relayout_event: bool, - - /// Profile which events script threads spend their time on. - pub profile_script_events: bool, - - /// Enable all heartbeats for profiling. - pub profile_heartbeats: bool, - - /// Paint borders along layer and tile boundaries. - pub show_compositor_borders: bool, - - /// Paint borders along fragment boundaries. - pub show_fragment_borders: bool, - - /// Overlay tiles with colors showing which thread painted them. - pub show_parallel_paint: bool, - - /// Mark which thread laid each flow out with colors. - pub show_parallel_layout: bool, - - /// Overlay repainted areas with a random color. - pub paint_flashing: bool, - - /// Write layout trace to an external file for debugging. - pub trace_layout: bool, - - /// Disable the style sharing cache. - pub disable_share_style_cache: bool, - - /// Whether to show in stdout style sharing cache stats after a restyle. - pub style_sharing_stats: bool, - - /// Translate mouse input into touch events. - pub convert_mouse_to_touch: bool, - - /// Replace unpaires surrogates in DOM strings with U+FFFD. - /// See https://github.com/servo/servo/issues/6564 - pub replace_surrogates: bool, - - /// Log GC passes and their durations. - pub gc_profile: bool, - - /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. - pub load_webfonts_synchronously: bool, - - /// Disable vsync in the compositor - pub disable_vsync: bool, - - /// Show webrender profiling stats on screen. - pub webrender_stats: bool, - - /// Show webrender debug on screen. - pub webrender_debug: bool, - - /// Enable webrender recording. - pub webrender_record: bool, - - /// Use multisample antialiasing in WebRender. - pub use_msaa: bool, - - // don't skip any backtraces on panic - pub full_backtraces: bool, - - /// 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. - pub precache_shaders: bool, - - /// True to use OS native signposting facilities. This makes profiling events (script activity, - /// reflow, compositing, etc.) appear in Instruments.app on macOS. - pub signpost: bool, -} - - -impl DebugOptions { - pub fn extend(&mut self, debug_string: String) -> Result<(), String> { - for option in debug_string.split(',') { - match option { - "help" => self.help = true, - "bubble-widths" => self.bubble_widths = true, - "disable-text-aa" => self.disable_text_aa = true, - "enable-subpixel-aa" => self.enable_subpixel_aa = true, - "disable-canvas-aa" => self.disable_text_aa = true, - "dump-style-tree" => self.dump_style_tree = true, - "dump-rule-tree" => self.dump_rule_tree = true, - "dump-flow-tree" => self.dump_flow_tree = true, - "dump-display-list" => self.dump_display_list = true, - "dump-display-list-json" => self.dump_display_list_json = true, - "dump-layer-tree" => self.dump_layer_tree = true, - "relayout-event" => self.relayout_event = true, - "profile-script-events" => self.profile_script_events = true, - "profile-heartbeats" => self.profile_heartbeats = true, - "show-compositor-borders" => self.show_compositor_borders = true, - "show-fragment-borders" => self.show_fragment_borders = true, - "show-parallel-paint" => self.show_parallel_paint = true, - "show-parallel-layout" => self.show_parallel_layout = true, - "paint-flashing" => self.paint_flashing = true, - "trace-layout" => self.trace_layout = true, - "disable-share-style-cache" => self.disable_share_style_cache = true, - "style-sharing-stats" => self.style_sharing_stats = true, - "convert-mouse-to-touch" => self.convert_mouse_to_touch = true, - "replace-surrogates" => self.replace_surrogates = true, - "gc-profile" => self.gc_profile = true, - "load-webfonts-synchronously" => self.load_webfonts_synchronously = true, - "disable-vsync" => self.disable_vsync = true, - "wr-stats" => self.webrender_stats = true, - "wr-debug" => self.webrender_debug = true, - "wr-record" => self.webrender_record = true, - "msaa" => self.use_msaa = true, - "full-backtraces" => self.full_backtraces = true, - "precache-shaders" => self.precache_shaders = true, - "signpost" => self.signpost = true, - "" => {}, - _ => return Err(String::from(option)), - }; - }; - Ok(()) - } -} - - -fn print_debug_usage(app: &str) -> ! { - fn print_option(name: &str, description: &str) { - println!("\t{:<35} {}", name, description); - } - - println!("Usage: {} debug option,[options,...]\n\twhere options include\n\nOptions:", app); - - print_option("bubble-widths", "Bubble intrinsic widths separately like other engines."); - print_option("disable-text-aa", "Disable antialiasing of rendered text."); - print_option("disable-canvas-aa", "Disable antialiasing on the HTML canvas element."); - print_option("dump-style-tree", "Print the DOM with computed styles after each restyle."); - print_option("dump-flow-tree", "Print the flow tree after each layout."); - print_option("dump-display-list", "Print the display list after each layout."); - print_option("dump-display-list-json", "Print the display list in JSON form."); - print_option("dump-layer-tree", "Print the layer tree whenever it changes."); - print_option("relayout-event", "Print notifications when there is a relayout."); - print_option("profile-script-events", "Enable profiling of script-related events."); - print_option("profile-heartbeats", "Enable heartbeats for all thread categories."); - print_option("show-compositor-borders", "Paint borders along layer and tile boundaries."); - print_option("show-fragment-borders", "Paint borders along fragment boundaries."); - print_option("show-parallel-paint", "Overlay tiles with colors showing which thread painted them."); - print_option("show-parallel-layout", "Mark which thread laid each flow out with colors."); - print_option("paint-flashing", "Overlay repainted areas with a random color."); - print_option("trace-layout", "Write layout trace to an external file for debugging."); - print_option("disable-share-style-cache", - "Disable the style sharing cache."); - print_option("parallel-display-list-building", "Build display lists in parallel."); - print_option("convert-mouse-to-touch", "Send touch events instead of mouse events"); - print_option("replace-surrogates", "Replace unpaires surrogates in DOM strings with U+FFFD. \ - See https://github.com/servo/servo/issues/6564"); - print_option("gc-profile", "Log GC passes and their durations."); - print_option("load-webfonts-synchronously", - "Load web fonts synchronously to avoid non-deterministic network-driven reflows"); - print_option("disable-vsync", - "Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate"); - print_option("wr-stats", "Show WebRender profiler on screen."); - print_option("msaa", "Use multisample antialiasing in WebRender."); - print_option("full-backtraces", "Print full backtraces for all errors"); - print_option("wr-debug", "Display webrender tile borders. Must be used with -w option."); - print_option("precache-shaders", "Compile all shaders during init. Must be used with -w option."); - print_option("signpost", "Emit native OS signposts for profile events (currently macOS only)"); - - println!(""); - - process::exit(0) -} - -#[derive(Clone)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub enum OutputOptions { - FileName(String), - Stdout(f64) -} - -fn args_fail(msg: &str) -> ! { - writeln!(io::stderr(), "{}", msg).unwrap(); - process::exit(1) -} - -static MULTIPROCESS: AtomicBool = ATOMIC_BOOL_INIT; - -#[inline] -pub fn multiprocess() -> bool { - MULTIPROCESS.load(Ordering::Relaxed) -} - -enum UserAgent { - Desktop, - Android, -} - -fn default_user_agent_string(agent: UserAgent) -> &'static str { - #[cfg(all(target_os = "linux", target_arch = "x86_64"))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (X11; Linux x86_64; rv:37.0) Servo/1.0 Firefox/37.0"; - #[cfg(all(target_os = "linux", not(target_arch = "x86_64")))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (X11; Linux i686; rv:37.0) Servo/1.0 Firefox/37.0"; - - #[cfg(all(target_os = "windows", target_arch = "x86_64"))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:37.0) Servo/1.0 Firefox/37.0"; - #[cfg(all(target_os = "windows", not(target_arch = "x86_64")))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Windows NT 6.1; rv:37.0) Servo/1.0 Firefox/37.0"; - - #[cfg(not(any(target_os = "linux", target_os = "windows")))] - // Neither Linux nor Windows, so maybe OS X, and if not then OS X is an okay fallback. - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Servo/1.0 Firefox/37.0"; - - - match agent { - UserAgent::Desktop => { - DESKTOP_UA_STRING - } - UserAgent::Android => { - "Mozilla/5.0 (Android; Mobile; rv:37.0) Servo/1.0 Firefox/37.0" - } - } -} - -#[cfg(target_os = "android")] -const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android; - -#[cfg(not(target_os = "android"))] -const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; - -pub fn default_opts() -> Opts { - Opts { - is_running_problem_test: false, - url: Some(ServoUrl::parse("about:blank").unwrap()), - paint_threads: 1, - tile_size: 512, - device_pixels_per_px: None, - time_profiling: None, - time_profiler_trace_path: None, - mem_profiler_period: None, - nonincremental_layout: false, - userscripts: None, - user_stylesheets: Vec::new(), - output_file: None, - replace_surrogates: false, - gc_profile: false, - load_webfonts_synchronously: false, - headless: true, - hard_fail: true, - bubble_inline_sizes_separately: false, - show_debug_borders: false, - show_debug_fragment_borders: false, - show_debug_parallel_paint: false, - show_debug_parallel_layout: false, - paint_flashing: false, - enable_text_antialiasing: false, - enable_subpixel_text_antialiasing: false, - enable_canvas_antialiasing: false, - trace_layout: false, - debugger_port: None, - devtools_port: None, - webdriver_port: None, - initial_window_size: TypedSize2D::new(1024, 740), - user_agent: default_user_agent_string(DEFAULT_USER_AGENT).into(), - multiprocess: false, - random_pipeline_closure_probability: None, - random_pipeline_closure_seed: None, - sandbox: false, - dump_style_tree: false, - dump_rule_tree: false, - dump_flow_tree: false, - dump_display_list: false, - dump_display_list_json: false, - dump_layer_tree: false, - relayout_event: false, - profile_script_events: false, - profile_heartbeats: false, - disable_share_style_cache: false, - style_sharing_stats: false, - convert_mouse_to_touch: false, - exit_after_load: false, - no_native_titlebar: false, - enable_vsync: true, - webrender_stats: false, - use_msaa: false, - config_dir: None, - full_backtraces: false, - is_printing_version: false, - webrender_debug: false, - webrender_record: false, - precache_shaders: false, - signpost: false, - } -} - -pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { - let (app_name, args) = args.split_first().unwrap(); - - let mut opts = Options::new(); - opts.optflag("c", "cpu", "CPU painting"); - opts.optflag("g", "gpu", "GPU painting"); - opts.optopt("o", "output", "Output file", "output.png"); - opts.optopt("s", "size", "Size of tiles", "512"); - opts.optopt("", "device-pixel-ratio", "Device pixels per px", ""); - opts.optopt("t", "threads", "Number of paint threads", "1"); - opts.optflagopt("p", "profile", "Time profiler flag and either a TSV output filename \ - OR an interval for output to Stdout (blank for Stdout with interval of 5s)", "10 \ - OR time.tsv"); - opts.optflagopt("", "profiler-trace-path", - "Path to dump a self-contained HTML timeline of profiler traces", - ""); - opts.optflagopt("m", "memory-profile", "Memory profiler flag and output interval", "10"); - opts.optflag("x", "exit", "Exit after load flag"); - opts.optopt("y", "layout-threads", "Number of threads to use for layout", "1"); - opts.optflag("i", "nonincremental-layout", "Enable to turn off incremental layout."); - opts.optflagopt("", "userscripts", - "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.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"); - opts.optflagopt("", "remote-debugging-port", "Start remote debugger server on port", "2794"); - opts.optflagopt("", "devtools", "Start remote devtools server on port", "6000"); - opts.optflagopt("", "webdriver", "Start remote WebDriver server on port", "7000"); - opts.optopt("", "resolution", "Set window resolution.", "1024x740"); - opts.optopt("u", - "user-agent", - "Set custom user agent string (or android / desktop for platform default)", - "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"); - opts.optflag("M", "multiprocess", "Run in multiprocess mode"); - opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess"); - opts.optopt("", - "random-pipeline-closure-probability", - "Probability of randomly closing a pipeline (for testing constellation hardening).", - "0.0"); - opts.optopt("", "random-pipeline-closure-seed", "A fixed seed for repeatbility of random pipeline closure.", ""); - opts.optmulti("Z", "debug", - "A comma-separated string of debug options. Pass help to show available options.", ""); - opts.optflag("h", "help", "Print this message"); - opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources"); - opts.optopt("", "content-process" , "Run as a content process and connect to the given pipe", - "servo-ipc-channel.abcdefg"); - opts.optmulti("", "pref", - "A preference to set to enable", "dom.mozbrowser.enabled"); - opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); - opts.optflag("w", "webrender", "Use webrender backend"); - opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl"); - opts.optopt("", "config-dir", - "config directory following xdg spec on linux platform", ""); - opts.optflag("v", "version", "Display servo version information"); - - let opt_match = match opts.parse(args) { - Ok(m) => m, - 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); - }; - - // If this is the content process, we'll receive the real options over IPC. So just fill in - // some dummy options for now. - if let Some(content_process) = opt_match.opt_str("content-process") { - MULTIPROCESS.store(true, Ordering::SeqCst); - return ArgumentParsingResult::ContentProcess(content_process); - } - - let mut debug_options = DebugOptions::default(); - - for debug_string in opt_match.opt_strs("Z") { - if let Err(e) = debug_options.extend(debug_string) { - args_fail(&format!("error: unrecognized debug option: {}", e)); - } - } - - if debug_options.help { - print_debug_usage(app_name) - } - - let cwd = env::current_dir().unwrap(); - let homepage_pref = PREFS.get("shell.homepage"); - let url_opt = if !opt_match.free.is_empty() { - Some(&opt_match.free[0][..]) - } else { - homepage_pref.as_string() - }; - let is_running_problem_test = - url_opt - .as_ref() - .map_or(false, |url| - url.starts_with("http://web-platform.test:8000/2dcontext/drawing-images-to-the-canvas/") || - url.starts_with("http://web-platform.test:8000/_mozilla/mozilla/canvas/") || - url.starts_with("http://web-platform.test:8000/_mozilla/css/canvas_over_area.html")); - - let url = match url_opt { - Some(url_string) => { - parse_url_or_filename(&cwd, url_string) - .unwrap_or_else(|()| args_fail("URL parsing failed")) - }, - None => { - print_usage(app_name, &opts); - args_fail("servo asks that you provide a URL") - } - }; - - let tile_size: usize = match opt_match.opt_str("s") { - Some(tile_size_str) => tile_size_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -s ({})", err))), - None => 512, - }; - - let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str| - dppx_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --device-pixel-ratio ({})", err))) - ); - - let mut paint_threads: usize = match opt_match.opt_str("t") { - Some(paint_threads_str) => paint_threads_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -t ({})", err))), - None => cmp::max(num_cpus::get() * 3 / 4, 1), - }; - - // If only the flag is present, default to a 5 second period for both profilers - let time_profiling = if opt_match.opt_present("p") { - match opt_match.opt_str("p") { - Some(argument) => match argument.parse::<f64>() { - Ok(interval) => Some(OutputOptions::Stdout(interval)) , - Err(_) => Some(OutputOptions::FileName(argument)), - }, - None => Some(OutputOptions::Stdout(5.0 as f64)), - } - } else { - // if the p option doesn't exist: - None - }; - - if let Some(ref time_profiler_trace_path) = opt_match.opt_str("profiler-trace-path") { - let mut path = PathBuf::from(time_profiler_trace_path); - path.pop(); - if let Err(why) = fs::create_dir_all(&path) { - error!("Couldn't create/open {:?}: {:?}", - Path::new(time_profiler_trace_path).to_string_lossy(), why); - } - } - - let mem_profiler_period = opt_match.opt_default("m", "5").map(|period| { - period.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: -m ({})", err))) - }); - - let mut layout_threads: Option<usize> = opt_match.opt_str("y") - .map(|layout_threads_str| { - layout_threads_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -y ({})", err))) - }); - - let nonincremental_layout = opt_match.opt_present("i"); - - let random_pipeline_closure_probability = opt_match.opt_str("random-pipeline-closure-probability").map(|prob| - prob.parse().unwrap_or_else(|err| { - args_fail(&format!("Error parsing option: --random-pipeline-closure-probability ({})", err)) - }) - ); - - let random_pipeline_closure_seed = opt_match.opt_str("random-pipeline-closure-seed").map(|seed| - seed.parse().unwrap_or_else(|err| { - args_fail(&format!("Error parsing option: --random-pipeline-closure-seed ({})", err)) - }) - ); - - let mut bubble_inline_sizes_separately = debug_options.bubble_widths; - if debug_options.trace_layout { - paint_threads = 1; - layout_threads = Some(1); - bubble_inline_sizes_separately = true; - } - - let debugger_port = opt_match.opt_default("remote-debugging-port", "2794").map(|port| { - port.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --remote-debugging-port ({})", err))) - }); - - let devtools_port = opt_match.opt_default("devtools", "6000").map(|port| { - port.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --devtools ({})", err))) - }); - - let webdriver_port = opt_match.opt_default("webdriver", "7000").map(|port| { - port.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --webdriver ({})", err))) - }); - - let initial_window_size = match opt_match.opt_str("resolution") { - Some(res_string) => { - let res: Vec<u32> = res_string.split('x').map(|r| { - r.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --resolution ({})", err))) - }).collect(); - TypedSize2D::new(res[0], res[1]) - } - None => { - TypedSize2D::new(1024, 740) - } - }; - - if opt_match.opt_present("M") { - MULTIPROCESS.store(true, Ordering::SeqCst) - } - - let user_agent = match opt_match.opt_str("u") { - Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android).into(), - Some(ref ua) if ua == "desktop" => default_user_agent_string(UserAgent::Desktop).into(), - Some(ua) => ua.into(), - None => default_user_agent_string(DEFAULT_USER_AGENT).into(), - }; - - let user_stylesheets = opt_match.opt_strs("user-stylesheet").iter().map(|filename| { - let path = cwd.join(filename); - let url = ServoUrl::from_url(Url::from_file_path(&path).unwrap()); - let mut contents = Vec::new(); - File::open(path) - .unwrap_or_else(|err| args_fail(&format!("Couldn't open {}: {}", filename, err))) - .read_to_end(&mut contents) - .unwrap_or_else(|err| args_fail(&format!("Couldn't read {}: {}", filename, err))); - (contents, url) - }).collect(); - - let do_not_use_native_titlebar = - opt_match.opt_present("b") || - !PREFS.get("shell.native-titlebar.enabled").as_boolean().unwrap(); - - let is_printing_version = opt_match.opt_present("v") || opt_match.opt_present("version"); - - let opts = Opts { - is_running_problem_test: is_running_problem_test, - url: Some(url), - paint_threads: paint_threads, - tile_size: tile_size, - device_pixels_per_px: device_pixels_per_px, - time_profiling: time_profiling, - time_profiler_trace_path: opt_match.opt_str("profiler-trace-path"), - mem_profiler_period: mem_profiler_period, - nonincremental_layout: nonincremental_layout, - userscripts: opt_match.opt_default("userscripts", ""), - user_stylesheets: user_stylesheets, - output_file: opt_match.opt_str("o"), - replace_surrogates: debug_options.replace_surrogates, - gc_profile: debug_options.gc_profile, - load_webfonts_synchronously: debug_options.load_webfonts_synchronously, - headless: opt_match.opt_present("z"), - hard_fail: opt_match.opt_present("f") && !opt_match.opt_present("F"), - bubble_inline_sizes_separately: bubble_inline_sizes_separately, - profile_script_events: debug_options.profile_script_events, - profile_heartbeats: debug_options.profile_heartbeats, - trace_layout: debug_options.trace_layout, - debugger_port: debugger_port, - devtools_port: devtools_port, - webdriver_port: webdriver_port, - initial_window_size: initial_window_size, - user_agent: user_agent, - multiprocess: opt_match.opt_present("M"), - sandbox: opt_match.opt_present("S"), - random_pipeline_closure_probability: random_pipeline_closure_probability, - random_pipeline_closure_seed: random_pipeline_closure_seed, - show_debug_borders: debug_options.show_compositor_borders, - show_debug_fragment_borders: debug_options.show_fragment_borders, - show_debug_parallel_paint: debug_options.show_parallel_paint, - show_debug_parallel_layout: debug_options.show_parallel_layout, - paint_flashing: debug_options.paint_flashing, - enable_text_antialiasing: !debug_options.disable_text_aa, - enable_subpixel_text_antialiasing: debug_options.enable_subpixel_aa, - enable_canvas_antialiasing: !debug_options.disable_canvas_aa, - dump_style_tree: debug_options.dump_style_tree, - dump_rule_tree: debug_options.dump_rule_tree, - dump_flow_tree: debug_options.dump_flow_tree, - dump_display_list: debug_options.dump_display_list, - dump_display_list_json: debug_options.dump_display_list_json, - dump_layer_tree: debug_options.dump_layer_tree, - relayout_event: debug_options.relayout_event, - disable_share_style_cache: debug_options.disable_share_style_cache, - style_sharing_stats: debug_options.style_sharing_stats, - convert_mouse_to_touch: debug_options.convert_mouse_to_touch, - exit_after_load: opt_match.opt_present("x"), - no_native_titlebar: do_not_use_native_titlebar, - enable_vsync: !debug_options.disable_vsync, - webrender_stats: debug_options.webrender_stats, - use_msaa: debug_options.use_msaa, - config_dir: opt_match.opt_str("config-dir").map(Into::into), - full_backtraces: debug_options.full_backtraces, - is_printing_version: is_printing_version, - webrender_debug: debug_options.webrender_debug, - webrender_record: debug_options.webrender_record, - precache_shaders: debug_options.precache_shaders, - signpost: debug_options.signpost, - }; - - set_defaults(opts); - - // These must happen after setting the default options, since the prefs rely on - // on the resource path. - // Note that command line preferences have the highest precedence - - prefs::add_user_prefs(); - - for pref in opt_match.opt_strs("pref").iter() { - let split: Vec<&str> = pref.splitn(2, '=').collect(); - let pref_name = split[0]; - let value = split.get(1); - match value { - Some(&"false") => PREFS.set(pref_name, PrefValue::Boolean(false)), - Some(&"true") | None => PREFS.set(pref_name, PrefValue::Boolean(true)), - _ => PREFS.set(pref_name, PrefValue::String(value.unwrap().to_string())) - }; - } - - if let Some(layout_threads) = layout_threads { - PREFS.set("layout.threads", PrefValue::Number(layout_threads as f64)); - } else if let Some(layout_threads) = PREFS.get("layout.threads").as_string() { - PREFS.set("layout.threads", PrefValue::Number(layout_threads.parse::<f64>().unwrap())); - } else if *PREFS.get("layout.threads") == PrefValue::Missing { - let layout_threads = cmp::max(num_cpus::get() * 3 / 4, 1); - PREFS.set("layout.threads", PrefValue::Number(layout_threads as f64)); - } - - ArgumentParsingResult::ChromeProcess -} - -pub enum ArgumentParsingResult { - ChromeProcess, - ContentProcess(String), -} - -// Make Opts available globally. This saves having to clone and pass -// opts everywhere it is used, which gets particularly cumbersome -// when passing through the DOM structures. -static mut DEFAULT_OPTIONS: *mut Opts = 0 as *mut Opts; -const INVALID_OPTIONS: *mut Opts = 0x01 as *mut Opts; - -lazy_static! { - static ref OPTIONS: Opts = { - unsafe { - let initial = if !DEFAULT_OPTIONS.is_null() { - let opts = Box::from_raw(DEFAULT_OPTIONS); - *opts - } else { - default_opts() - }; - DEFAULT_OPTIONS = INVALID_OPTIONS; - initial - } - }; -} - -pub fn set_defaults(opts: Opts) { - unsafe { - assert!(DEFAULT_OPTIONS.is_null()); - assert!(DEFAULT_OPTIONS != INVALID_OPTIONS); - let box_opts = Box::new(opts); - DEFAULT_OPTIONS = Box::into_raw(box_opts); - } -} - -#[inline] -pub fn get() -> &'static Opts { - &OPTIONS -} - -pub fn parse_url_or_filename(cwd: &Path, input: &str) -> Result<ServoUrl, ()> { - match ServoUrl::parse(input) { - Ok(url) => Ok(url), - Err(url::ParseError::RelativeUrlWithoutBase) => { - Url::from_file_path(&*cwd.join(input)).map(ServoUrl::from_url) - } - Err(_) => Err(()), - } -} - -impl Opts { - pub fn should_use_osmesa(&self) -> bool { - self.headless - } -} diff --git a/components/util/prefs.rs b/components/util/prefs.rs deleted file mode 100644 index c0ad11bfe0b..00000000000 --- a/components/util/prefs.rs +++ /dev/null @@ -1,262 +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 basedir::default_config_dir; -use opts; -use resource_files::resources_dir_path; -use rustc_serialize::json::{Json, ToJson}; -use std::borrow::ToOwned; -use std::collections::HashMap; -use std::fs::File; -use std::io::{Read, Write, stderr}; -use std::path::PathBuf; -use std::sync::{Arc, RwLock}; - -lazy_static! { - pub static ref PREFS: Preferences = { - let prefs = read_prefs().ok().unwrap_or_else(HashMap::new); - Preferences(Arc::new(RwLock::new(prefs))) - }; -} - -#[derive(PartialEq, Clone, Debug)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub enum PrefValue { - Boolean(bool), - String(String), - Number(f64), - Missing -} - -impl PrefValue { - pub fn from_json(data: Json) -> Result<PrefValue, ()> { - let value = match data { - Json::Boolean(x) => PrefValue::Boolean(x), - Json::String(x) => PrefValue::String(x), - Json::F64(x) => PrefValue::Number(x), - Json::I64(x) => PrefValue::Number(x as f64), - Json::U64(x) => PrefValue::Number(x as f64), - _ => return Err(()) - }; - Ok(value) - } - - pub fn as_boolean(&self) -> Option<bool> { - match *self { - PrefValue::Boolean(value) => { - Some(value) - }, - _ => None - } - } - - pub fn as_string(&self) -> Option<&str> { - match *self { - PrefValue::String(ref value) => { - Some(&value) - }, - _ => None - } - } - - pub fn as_i64(&self) -> Option<i64> { - match *self { - PrefValue::Number(x) => Some(x as i64), - _ => None, - } - } - - pub fn as_u64(&self) -> Option<u64> { - match *self { - PrefValue::Number(x) => Some(x as u64), - _ => None, - } - } -} - -impl ToJson for PrefValue { - fn to_json(&self) -> Json { - match *self { - PrefValue::Boolean(x) => { - Json::Boolean(x) - }, - PrefValue::String(ref x) => { - Json::String(x.clone()) - }, - PrefValue::Number(x) => { - Json::F64(x) - }, - PrefValue::Missing => Json::Null - } - } -} - -#[derive(Clone, Debug)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub enum Pref { - NoDefault(Arc<PrefValue>), - WithDefault(Arc<PrefValue>, Option<Arc<PrefValue>>) -} - - -impl Pref { - pub fn new(value: PrefValue) -> Pref { - Pref::NoDefault(Arc::new(value)) - } - - fn new_default(value: PrefValue) -> Pref { - Pref::WithDefault(Arc::new(value), None) - } - - fn from_json(data: Json) -> Result<Pref, ()> { - let value = try!(PrefValue::from_json(data)); - Ok(Pref::new_default(value)) - } - - pub fn value(&self) -> &Arc<PrefValue> { - match *self { - Pref::NoDefault(ref x) => x, - Pref::WithDefault(ref default, ref override_value) => { - match *override_value { - Some(ref x) => x, - None => default - } - } - } - } - - fn set(&mut self, value: PrefValue) { - // TODO - this should error if we try to override a pref of one type - // with a value of a different type - match *self { - Pref::NoDefault(ref mut pref_value) => { - *pref_value = Arc::new(value) - }, - Pref::WithDefault(_, ref mut override_value) => { - *override_value = Some(Arc::new(value)) - } - } - } -} - -impl ToJson for Pref { - fn to_json(&self) -> Json { - self.value().to_json() - } -} - -pub fn read_prefs_from_file<T>(mut file: T) - -> Result<HashMap<String, Pref>, ()> where T: Read { - let json = try!(Json::from_reader(&mut file).or_else(|e| { - println!("Ignoring invalid JSON in preferences: {:?}.", e); - Err(()) - })); - - let mut prefs = HashMap::new(); - if let Json::Object(obj) = json { - for (name, value) in obj.into_iter() { - match Pref::from_json(value) { - Ok(x) => { - prefs.insert(name, x); - }, - Err(_) => println!("Ignoring non-boolean/string/i64 preference value for {:?}", name), - } - } - } - Ok(prefs) -} - -pub fn add_user_prefs() { - match opts::get().config_dir { - Some(ref config_path) => { - let mut path = PathBuf::from(config_path); - init_user_prefs(&mut path); - } - None => { - let mut path = default_config_dir().unwrap(); - if path.join("prefs.json").exists() { - init_user_prefs(&mut path); - } - } - } -} - -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) { - PREFS.extend(prefs); - } - } else { - writeln!(&mut stderr(), "Error opening prefs.json from config directory") - .expect("failed printing to stderr"); - } -} - -fn read_prefs() -> Result<HashMap<String, Pref>, ()> { - let mut path = try!(resources_dir_path().map_err(|_| ())); - path.push("prefs.json"); - - let file = try!(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 { - pub fn get(&self, name: &str) -> Arc<PrefValue> { - self.0.read().unwrap().get(name).map_or(Arc::new(PrefValue::Missing), |x| x.value().clone()) - } - - pub fn cloned(&self) -> HashMap<String, Pref> { - self.0.read().unwrap().clone() - } - - pub fn is_mozbrowser_enabled(&self) -> bool { - self.get("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) - } - - pub fn set(&self, name: &str, value: PrefValue) { - let mut prefs = self.0.write().unwrap(); - if let Some(pref) = prefs.get_mut(name) { - pref.set(value); - return; - } - prefs.insert(name.to_owned(), Pref::new(value)); - } - - pub fn reset(&self, name: &str) -> Arc<PrefValue> { - let mut prefs = self.0.write().unwrap(); - let result = match prefs.get_mut(name) { - None => return Arc::new(PrefValue::Missing), - Some(&mut Pref::NoDefault(_)) => Arc::new(PrefValue::Missing), - Some(&mut Pref::WithDefault(ref default, ref mut set_value)) => { - *set_value = None; - default.clone() - }, - }; - if *result == PrefValue::Missing { - prefs.remove(name); - } - result - } - - pub fn reset_all(&self) { - let names = { - self.0.read().unwrap().keys().cloned().collect::<Vec<String>>() - }; - for name in names.iter() { - self.reset(name); - } - } - - pub fn extend(&self, extension: HashMap<String, Pref>) { - self.0.write().unwrap().extend(extension); - } -} diff --git a/components/util/remutex.rs b/components/util/remutex.rs deleted file mode 100644 index a574de9cfb3..00000000000 --- a/components/util/remutex.rs +++ /dev/null @@ -1,234 +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/. */ - -//! An implementation of re-entrant mutexes. -//! -//! Re-entrant mutexes are like mutexes, but where it is expected -//! that a single thread may own a lock more than once. - -//! It provides the same interface as https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/remutex.rs -//! so if those types are ever exported, we should be able to replace this implemtation. - -use core::nonzero::NonZero; -use std::cell::{Cell, UnsafeCell}; -use std::ops::Deref; -use std::sync::{LockResult, Mutex, MutexGuard, PoisonError, TryLockError, TryLockResult}; -use std::sync::atomic::{AtomicUsize, Ordering}; - -/// A type for thread ids. - -// TODO: can we use the thread-id crate for this? - -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -pub struct ThreadId(NonZero<usize>); - -lazy_static!{ static ref THREAD_COUNT: AtomicUsize = AtomicUsize::new(1); } - -impl ThreadId { - #[allow(unsafe_code)] - fn new() -> ThreadId { - let number = THREAD_COUNT.fetch_add(1, Ordering::SeqCst); - ThreadId(unsafe { NonZero::new(number) }) - } - pub fn current() -> ThreadId { - THREAD_ID.with(|tls| tls.clone()) - } -} - -thread_local!{ static THREAD_ID: ThreadId = ThreadId::new() } - -/// A type for atomic storage of thread ids. -#[derive(Debug)] -pub struct AtomicOptThreadId(AtomicUsize); - -impl AtomicOptThreadId { - pub fn new() -> AtomicOptThreadId { - AtomicOptThreadId(AtomicUsize::new(0)) - } - pub fn store(&self, value: Option<ThreadId>, ordering: Ordering) { - let number = value.map(|id| *id.0).unwrap_or(0); - self.0.store(number, ordering); - } - #[allow(unsafe_code)] - pub fn load(&self, ordering: Ordering) -> Option<ThreadId> { - let number = self.0.load(ordering); - if number == 0 { None } else { Some(ThreadId(unsafe { NonZero::new(number) })) } - } - #[allow(unsafe_code)] - pub fn swap(&self, value: Option<ThreadId>, ordering: Ordering) -> Option<ThreadId> { - let number = value.map(|id| *id.0).unwrap_or(0); - let number = self.0.swap(number, ordering); - if number == 0 { None } else { Some(ThreadId(unsafe { NonZero::new(number) })) } - } -} - -/// A type for hand-over-hand mutexes. -/// -/// These support `lock` and `unlock` functions. `lock` blocks waiting to become the -/// mutex owner. `unlock` can only be called by the lock owner, and panics otherwise. -/// They have the same happens-before and poisoning semantics as `Mutex`. - -// TODO: Can we use `raw_lock` and `raw_unlock` from `parking_lot`'s `Mutex` for this? - -pub struct HandOverHandMutex { - mutex: Mutex<()>, - owner: AtomicOptThreadId, - guard: UnsafeCell<Option<MutexGuard<'static, ()>>>, -} - -impl HandOverHandMutex { - pub fn new() -> HandOverHandMutex { - HandOverHandMutex { - mutex: Mutex::new(()), - owner: AtomicOptThreadId::new(), - guard: UnsafeCell::new(None), - } - } - #[allow(unsafe_code)] - unsafe fn set_guard_and_owner<'a>(&'a self, guard: MutexGuard<'a, ()>) { - // The following two lines allow us to unsafely store - // Some(guard): Option<MutexGuard<'a, ()> - // in self.guard, even though its contents are Option<MutexGuard<'static, ()>>, - // that is the lifetime is 'a not 'static. - let guard_ptr = &mut *(self.guard.get() as *mut u8 as *mut Option<MutexGuard<'a, ()>>); - *guard_ptr = Some(guard); - self.owner.store(Some(ThreadId::current()), Ordering::Relaxed); - } - #[allow(unsafe_code)] - unsafe fn unset_guard_and_owner(&self) { - let guard_ptr = &mut *self.guard.get(); - let old_owner = self.owner(); - self.owner.store(None, Ordering::Relaxed); - // Make sure we release the lock before checking the assertions. - // We protect logging by a re-entrant lock, so we don't want - // to do any incidental logging while we the lock is held. - drop(guard_ptr.take()); - // Now we have released the lock, it's okay to use logging. - assert_eq!(old_owner, Some(ThreadId::current())); - } - #[allow(unsafe_code)] - pub fn lock<'a>(&'a self) -> LockResult<()> { - let (guard, result) = match self.mutex.lock() { - Ok(guard) => (guard, Ok(())), - Err(err) => (err.into_inner(), Err(PoisonError::new(()))), - }; - unsafe { self.set_guard_and_owner(guard); } - result - } - #[allow(unsafe_code)] - pub fn try_lock(&self) -> TryLockResult<()> { - let (guard, result) = match self.mutex.try_lock() { - Ok(guard) => (guard, Ok(())), - Err(TryLockError::WouldBlock) => return Err(TryLockError::WouldBlock), - Err(TryLockError::Poisoned(err)) => (err.into_inner(), Err(TryLockError::Poisoned(PoisonError::new(())))), - }; - unsafe { self.set_guard_and_owner(guard); } - result - } - #[allow(unsafe_code)] - pub fn unlock(&self) { - unsafe { self.unset_guard_and_owner(); } - } - pub fn owner(&self) -> Option<ThreadId> { - self.owner.load(Ordering::Relaxed) - } -} - -#[allow(unsafe_code)] -unsafe impl Send for HandOverHandMutex {} - -/// A type for re-entrant mutexes. -/// -/// It provides the same interface as https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/remutex.rs - -pub struct ReentrantMutex<T> { - mutex: HandOverHandMutex, - count: Cell<usize>, - data: T, -} - -#[allow(unsafe_code)] -unsafe impl<T> Sync for ReentrantMutex<T> where T: Send {} - -impl<T> ReentrantMutex<T> { - pub fn new(data: T) -> ReentrantMutex<T> { - debug!("{:?} Creating new lock.", ThreadId::current()); - ReentrantMutex { - mutex: HandOverHandMutex::new(), - count: Cell::new(0), - data: data, - } - } - - pub fn lock(&self) -> LockResult<ReentrantMutexGuard<T>> { - debug!("{:?} Locking.", ThreadId::current()); - if self.mutex.owner() != Some(ThreadId::current()) { - debug!("{:?} Becoming owner.", ThreadId::current()); - if let Err(_) = self.mutex.lock() { - debug!("{:?} Poison!", ThreadId::current()); - return Err(PoisonError::new(self.mk_guard())); - } - debug!("{:?} Became owner.", ThreadId::current()); - } - Ok(self.mk_guard()) - } - - pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<T>> { - debug!("{:?} Try locking.", ThreadId::current()); - if self.mutex.owner() != Some(ThreadId::current()) { - debug!("{:?} Becoming owner?", ThreadId::current()); - if let Err(err) = self.mutex.try_lock() { - match err { - TryLockError::WouldBlock => { - debug!("{:?} Would block.", ThreadId::current()); - return Err(TryLockError::WouldBlock) - }, - TryLockError::Poisoned(_) => { - debug!("{:?} Poison!", ThreadId::current()); - return Err(TryLockError::Poisoned(PoisonError::new(self.mk_guard()))); - }, - } - } - debug!("{:?} Became owner.", ThreadId::current()); - } - Ok(self.mk_guard()) - } - - fn unlock(&self) { - debug!("{:?} Unlocking.", ThreadId::current()); - let count = self.count.get().checked_sub(1).expect("Underflowed lock count."); - debug!("{:?} Decrementing count to {}.", ThreadId::current(), count); - self.count.set(count); - if count == 0 { - debug!("{:?} Releasing mutex.", ThreadId::current()); - self.mutex.unlock(); - } - } - - fn mk_guard(&self) -> ReentrantMutexGuard<T> { - let count = self.count.get().checked_add(1).expect("Overflowed lock count."); - debug!("{:?} Incrementing count to {}.", ThreadId::current(), count); - self.count.set(count); - ReentrantMutexGuard { mutex: self } - } -} - -#[must_use] -pub struct ReentrantMutexGuard<'a, T> where T: 'static { - mutex: &'a ReentrantMutex<T>, -} - -impl<'a, T> Drop for ReentrantMutexGuard<'a, T> { - #[allow(unsafe_code)] - fn drop(&mut self) { - self.mutex.unlock() - } -} - -impl<'a, T> Deref for ReentrantMutexGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - &self.mutex.data - } -} diff --git a/components/util/resource_files.rs b/components/util/resource_files.rs deleted file mode 100644 index 4a155ecf51e..00000000000 --- a/components/util/resource_files.rs +++ /dev/null @@ -1,67 +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(not(target_os = "android"))] -use std::env; -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")] -pub fn resources_dir_path() -> io::Result<PathBuf> { - Ok(PathBuf::from("/sdcard/servo/")) -} - -#[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 = try!(env::current_exe()); - // Follow symlink - path = try!(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 = try!(resources_dir_path()); - path.push(relative_path); - let mut file = try!(File::open(&path)); - let mut data = Vec::new(); - try!(file.read_to_end(&mut data)); - Ok(data) -} diff --git a/components/util/thread.rs b/components/util/thread.rs deleted file mode 100644 index 130187244db..00000000000 --- a/components/util/thread.rs +++ /dev/null @@ -1,11 +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 std::thread; - -pub fn spawn_named<F>(name: String, f: F) - where F: FnOnce() + Send + 'static -{ - thread::Builder::new().name(name).spawn(f).expect("Thread spawn failed"); -} |