servo/components/config/prefs.rs
Martin Robinson d31cdb682f
Make the choice of layout runtime setting
Co-authored-by: Samson <16504129+sagudev@users.noreply.github.com>
2023-07-06 14:49:24 +02:00

500 lines
16 KiB
Rust

/* 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 https://mozilla.org/MPL/2.0/. */
use embedder_traits::resources::{self, Resource};
use serde_json::{self, Value};
use std::borrow::ToOwned;
use std::collections::HashMap;
use crate::pref_util::Preferences;
pub use crate::pref_util::{PrefError, PrefValue};
use gen::Prefs;
lazy_static! {
static ref PREFS: Preferences<'static, Prefs> = {
let def_prefs: Prefs = serde_json::from_str(&resources::read_string(Resource::Preferences))
.expect("Failed to initialize config preferences.");
Preferences::new(def_prefs, &gen::PREF_ACCESSORS)
};
}
/// A convenience macro for accessing a preference value using its static path.
/// Passing an invalid path is a compile-time error.
#[macro_export]
macro_rules! pref {
($($segment: ident).+) => {{
let values = $crate::prefs::pref_map().values();
let lock = values.read()
.map(|prefs| prefs $(.$segment)+.clone());
lock.unwrap()
}};
}
/// A convenience macro for updating a preference value using its static path.
/// Passing an invalid path is a compile-time error.
#[macro_export]
macro_rules! set_pref {
($($segment: ident).+, $value: expr) => {{
let values = $crate::prefs::pref_map().values();
let mut lock = values.write().unwrap();
lock$ (.$segment)+ = $value;
}};
}
/// Access preferences using their `String` keys. Note that the key may be different from the
/// static path because legacy keys contain hyphens, or because a preference name has been renamed.
///
/// When retrieving a preference, the value will always be a `PrefValue`. When setting a value, it
/// may be a `PrefValue` or the type that converts into the correct underlying value; one of `bool`,
/// `i64`, `f64` or `String`.
#[inline]
pub fn pref_map() -> &'static Preferences<'static, Prefs> {
&PREFS
}
pub fn add_user_prefs(prefs: HashMap<String, PrefValue>) {
if let Err(error) = PREFS.set_all(prefs.into_iter()) {
panic!("Error setting preference: {:?}", error);
}
}
pub fn read_prefs_map(txt: &str) -> Result<HashMap<String, PrefValue>, PrefError> {
let prefs: HashMap<String, Value> =
serde_json::from_str(txt).map_err(|e| PrefError::JsonParseErr(e))?;
prefs
.into_iter()
.map(|(k, pref_value)| {
Ok({
let v = match &pref_value {
Value::Bool(b) => PrefValue::Bool(*b),
Value::Number(n) if n.is_i64() => PrefValue::Int(n.as_i64().unwrap()),
Value::Number(n) if n.is_f64() => PrefValue::Float(n.as_f64().unwrap()),
Value::String(s) => PrefValue::Str(s.to_owned()),
_ => {
return Err(PrefError::InvalidValue(format!(
"Invalid value: {}",
pref_value
)));
},
};
(k.to_owned(), v)
})
})
.collect()
}
mod gen {
use servo_config_plugins::build_structs;
// The number of layout threads is calculated if it is not present in `prefs.json`.
fn default_layout_threads() -> i64 {
std::cmp::max(num_cpus::get() * 3 / 4, 1) as i64
}
fn black() -> i64 {
0x000000
}
fn white() -> i64 {
0xFFFFFF
}
build_structs! {
// type of the accessors
accessor_type = crate::pref_util::Accessor::<Prefs, crate::pref_util::PrefValue>,
// name of the constant, which will hold a HashMap of preference accessors
gen_accessors = PREF_ACCESSORS,
// tree of structs to generate
gen_types = Prefs {
browser: {
display: {
#[serde(default = "white")]
background_color: i64,
#[serde(default = "black")]
foreground_color: i64,
}
},
css: {
animations: {
testing: {
#[serde(default)]
enabled: bool,
},
},
},
devtools: {
server: {
enabled: bool,
port: i64,
},
},
dom: {
webgpu: {
enabled: bool,
},
bluetooth: {
enabled: bool,
testing: {
enabled: bool,
}
},
canvas_capture: {
enabled: bool,
},
canvas_text: {
enabled: bool,
},
composition_event: {
#[serde(rename = "dom.compositionevent.enabled")]
enabled: bool,
},
custom_elements: {
#[serde(rename = "dom.customelements.enabled")]
enabled: bool,
},
document: {
dblclick_timeout: i64,
dblclick_dist: i64,
},
forcetouch: {
enabled: bool,
},
fullscreen: {
test: bool,
},
gamepad: {
enabled: bool,
},
imagebitmap: {
enabled: bool,
},
microdata: {
testing: {
enabled: bool,
}
},
mouse_event: {
which: {
#[serde(rename = "dom.mouseevent.which.enabled")]
enabled: bool,
}
},
mutation_observer: {
enabled: bool,
},
offscreen_canvas: {
enabled: bool,
},
permissions: {
enabled: bool,
testing: {
allowed_in_nonsecure_contexts: bool,
}
},
script: {
asynch: bool,
},
serviceworker: {
enabled: bool,
timeout_seconds: i64,
},
servo_helpers: {
enabled: bool,
},
servoparser: {
async_html_tokenizer: {
enabled: bool,
}
},
shadowdom: {
enabled: bool,
},
svg: {
enabled: bool,
},
testable_crash: {
enabled: bool,
},
testbinding: {
enabled: bool,
prefcontrolled: {
#[serde(default)]
enabled: bool,
},
prefcontrolled2: {
#[serde(default)]
enabled: bool,
},
preference_value: {
#[serde(default)]
falsy: bool,
#[serde(default)]
quote_string_test: String,
#[serde(default)]
space_string_test: String,
#[serde(default)]
string_empty: String,
#[serde(default)]
string_test: String,
#[serde(default)]
truthy: bool,
},
},
testing: {
element: {
activation: {
#[serde(default)]
enabled: bool,
}
},
html_input_element: {
select_files: {
#[serde(rename = "dom.testing.htmlinputelement.select_files.enabled")]
enabled: bool,
}
},
},
testperf: {
#[serde(default)]
enabled: bool,
},
webgl2: {
enabled: bool,
},
webrtc: {
transceiver: {
enabled: bool,
},
#[serde(default)]
enabled: bool,
},
webvtt: {
enabled: bool,
},
webxr: {
#[serde(default)]
enabled: bool,
#[serde(default)]
test: bool,
first_person_observer_view: bool,
glwindow: {
#[serde(default)]
enabled: bool,
#[serde(rename = "dom.webxr.glwindow.left-right")]
left_right: bool,
#[serde(rename = "dom.webxr.glwindow.red-cyan")]
red_cyan: bool,
spherical: bool,
cubemap: bool,
},
hands: {
#[serde(default)]
enabled: bool,
},
layers: {
enabled: bool,
},
sessionavailable: bool,
#[serde(rename = "dom.webxr.unsafe-assume-user-intent")]
unsafe_assume_user_intent: bool,
},
worklet: {
blockingsleep: {
#[serde(default)]
enabled: bool,
},
#[serde(default)]
enabled: bool,
testing: {
#[serde(default)]
enabled: bool,
},
timeout_ms: i64,
},
},
gfx: {
subpixel_text_antialiasing: {
#[serde(rename = "gfx.subpixel-text-antialiasing.enabled")]
enabled: bool,
},
texture_swizzling: {
#[serde(rename = "gfx.texture-swizzling.enabled")]
enabled: bool,
},
},
js: {
asmjs: {
enabled: bool,
},
asyncstack: {
enabled: bool,
},
baseline: {
enabled: bool,
unsafe_eager_compilation: {
enabled: bool,
},
},
discard_system_source: {
enabled: bool,
},
dump_stack_on_debuggee_would_run: {
enabled: bool,
},
ion: {
enabled: bool,
offthread_compilation: {
enabled: bool,
},
unsafe_eager_compilation: {
enabled: bool,
},
},
mem: {
gc: {
allocation_threshold_mb: i64,
allocation_threshold_factor: i64,
allocation_threshold_avoid_interrupt_factor: i64,
compacting: {
enabled: bool,
},
decommit_threshold_mb: i64,
dynamic_heap_growth: {
enabled: bool,
},
dynamic_mark_slice: {
enabled: bool,
},
empty_chunk_count_max: i64,
empty_chunk_count_min: i64,
high_frequency_heap_growth_max: i64,
high_frequency_heap_growth_min: i64,
high_frequency_high_limit_mb: i64,
high_frequency_low_limit_mb: i64,
high_frequency_time_limit_ms: i64,
incremental: {
enabled: bool,
slice_ms: i64,
},
low_frequency_heap_growth: i64,
per_zone: {
enabled: bool,
},
zeal: {
frequency: i64,
level: i64,
},
},
max: i64,
},
native_regex: {
enabled: bool,
},
offthread_compilation: {
enabled: bool,
},
parallel_parsing: {
enabled: bool,
},
shared_memory: {
enabled: bool,
},
strict: {
debug: {
enabled: bool,
},
enabled: bool,
},
throw_on_asmjs_validation_failure: {
enabled: bool,
},
throw_on_debuggee_would_run: {
enabled: bool,
},
timers: {
minimum_duration: i64,
},
wasm: {
baseline: {
enabled: bool,
},
enabled: bool,
ion: {
enabled: bool,
}
},
werror: {
enabled: bool,
},
},
layout: {
animations: {
test: {
enabled: bool,
}
},
columns: {
enabled: bool,
},
flexbox: {
enabled: bool,
},
legacy_layout: bool,
#[serde(default = "default_layout_threads")]
threads: i64,
writing_mode: {
#[serde(rename = "layout.writing-mode.enabled")]
enabled: bool,
}
},
media: {
glvideo: {
enabled: bool,
},
testing: {
enabled: bool,
}
},
network: {
enforce_tls: {
enabled: bool,
localhost: bool,
onion: bool,
},
http_cache: {
#[serde(rename = "network.http-cache.disabled")]
disabled: bool,
},
mime: {
sniff: bool,
}
},
session_history: {
#[serde(rename = "session-history.max-length")]
max_length: i64,
},
shell: {
crash_reporter: {
enabled: bool,
},
homepage: String,
keep_screen_on: {
enabled: bool,
},
#[serde(rename = "shell.native-orientation")]
native_orientation: String,
native_titlebar: {
#[serde(rename = "shell.native-titlebar.enabled")]
enabled: bool,
},
searchpage: String,
},
webgl: {
testing: {
context_creation_error: bool,
}
},
}
}
}