servo/components/config/prefs.rs
Martin Robinson 4402b7cf8f
libservo: Remove a couple EmbedderMethods (#36276)
- Remove `EmbedderMethods::get_user_agent_string`. This is now part of
  the `Preferences` data structure, which should allow it to be
  per-`WebView` in the future.
- Remove `EmbedderMethods::get_version_string`. This was used to include
  some data along with WebRender captures about the Servo version. This
  isn't really necessary and it was done to replace code in the past
  that output the WebRender version, so also isn't what the original
  code did. I think we can just remove this entirely.

The idea with these changes is that `EmbedderMethods` can be removed
in a followup and the rest of the methods can be added to
`ServoDelegate`. These two methods are ones that cannot be added to a
delegate as they are used during `Servo` initialization.

Testing: There is currently no testing for libservo. These changes are
meant
as preparation for adding a suite of `WebView` unit tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-04-01 22:59:50 +00:00

478 lines
20 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 std::sync::{RwLock, RwLockReadGuard};
use serde::{Deserialize, Serialize};
use servo_config_macro::ServoPreferences;
pub use crate::pref_util::PrefValue;
static PREFERENCES: RwLock<Preferences> = RwLock::new(Preferences::const_default());
#[inline]
/// Get the current set of global preferences for Servo.
pub fn get() -> RwLockReadGuard<'static, Preferences> {
PREFERENCES.read().unwrap()
}
pub fn set(preferences: Preferences) {
// Map between Stylo preference names and Servo preference names as the This should be
// kept in sync with components/script/dom/bindings/codegen/run.py which generates the
// DOM CSS style accessors.
stylo_config::set_bool("layout.unimplemented", preferences.layout_unimplemented);
stylo_config::set_i32("layout.threads", preferences.layout_threads as i32);
stylo_config::set_bool("layout.flexbox.enabled", preferences.layout_flexbox_enabled);
stylo_config::set_bool("layout.columns.enabled", preferences.layout_columns_enabled);
stylo_config::set_bool("layout.grid.enabled", preferences.layout_grid_enabled);
stylo_config::set_bool(
"layout.css.transition-behavior.enabled",
preferences.layout_css_transition_behavior_enabled,
);
stylo_config::set_bool(
"layout.writing-mode.enabled",
preferences.layout_writing_mode_enabled,
);
stylo_config::set_bool(
"layout.container-queries.enabled",
preferences.layout_container_queries_enabled,
);
*PREFERENCES.write().unwrap() = preferences;
}
/// 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 {
($name: ident) => {
$crate::prefs::get().$name.clone()
};
}
#[derive(Clone, Deserialize, Serialize, ServoPreferences)]
pub struct Preferences {
pub fonts_default: String,
pub fonts_serif: String,
pub fonts_sans_serif: String,
pub fonts_monospace: String,
pub fonts_default_size: i64,
pub fonts_default_monospace_size: i64,
pub css_animations_testing_enabled: bool,
/// Start the devtools server at startup
pub devtools_server_enabled: bool,
/// Port number to start a server to listen to remote Firefox devtools connections.
/// 0 for random port.
pub devtools_server_port: i64,
pub dom_webgpu_enabled: bool,
/// List of comma-separated backends to be used by wgpu.
pub dom_webgpu_wgpu_backend: String,
pub dom_abort_controller_enabled: bool,
pub dom_bluetooth_enabled: bool,
pub dom_bluetooth_testing_enabled: bool,
pub dom_allow_scripts_to_close_windows: bool,
pub dom_canvas_capture_enabled: bool,
pub dom_canvas_text_enabled: bool,
pub dom_clipboardevent_enabled: bool,
pub dom_composition_event_enabled: bool,
pub dom_crypto_subtle_enabled: bool,
pub dom_customelements_enabled: bool,
pub dom_document_dblclick_timeout: i64,
pub dom_document_dblclick_dist: i64,
pub dom_fontface_enabled: bool,
pub dom_forcetouch_enabled: bool,
pub dom_fullscreen_test: bool,
pub dom_gamepad_enabled: bool,
pub dom_imagebitmap_enabled: bool,
pub dom_intersection_observer_enabled: bool,
pub dom_microdata_testing_enabled: bool,
pub dom_mouse_event_which_enabled: bool,
pub dom_mutation_observer_enabled: bool,
pub dom_notification_enabled: bool,
pub dom_offscreen_canvas_enabled: bool,
pub dom_permissions_enabled: bool,
pub dom_permissions_testing_allowed_in_nonsecure_contexts: bool,
pub dom_resize_observer_enabled: bool,
pub dom_script_asynch: bool,
pub dom_serviceworker_enabled: bool,
pub dom_serviceworker_timeout_seconds: i64,
pub dom_servo_helpers_enabled: bool,
pub dom_servoparser_async_html_tokenizer_enabled: bool,
pub dom_shadowdom_enabled: bool,
pub dom_svg_enabled: bool,
pub dom_testable_crash_enabled: bool,
pub dom_testbinding_enabled: bool,
pub dom_testbinding_prefcontrolled_enabled: bool,
pub dom_testbinding_prefcontrolled2_enabled: bool,
pub dom_testbinding_preference_value_falsy: bool,
pub dom_testbinding_preference_value_quote_string_test: String,
pub dom_testbinding_preference_value_space_string_test: String,
pub dom_testbinding_preference_value_string_empty: String,
pub dom_testbinding_preference_value_string_test: String,
pub dom_testbinding_preference_value_truthy: bool,
pub dom_testing_element_activation_enabled: bool,
pub dom_testing_html_input_element_select_files_enabled: bool,
pub dom_testperf_enabled: bool,
/// Enable the [URLPattern] API.
///
/// [URLPattern]: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern
pub dom_urlpattern_enabled: bool,
pub dom_xpath_enabled: bool,
/// Enable WebGL2 APIs.
pub dom_webgl2_enabled: bool,
pub dom_webrtc_enabled: bool,
pub dom_webrtc_transceiver_enabled: bool,
pub dom_webvtt_enabled: bool,
pub dom_webxr_enabled: bool,
pub dom_webxr_test: bool,
pub dom_webxr_first_person_observer_view: bool,
pub dom_webxr_glwindow_enabled: bool,
pub dom_webxr_glwindow_left_right: bool,
pub dom_webxr_glwindow_red_cyan: bool,
pub dom_webxr_glwindow_spherical: bool,
pub dom_webxr_glwindow_cubemap: bool,
pub dom_webxr_hands_enabled: bool,
pub dom_webxr_layers_enabled: bool,
pub dom_webxr_openxr_enabled: bool,
pub dom_webxr_sessionavailable: bool,
pub dom_webxr_unsafe_assume_user_intent: bool,
pub dom_worklet_enabled: bool,
pub dom_worklet_blockingsleep: bool,
pub dom_worklet_testing_enabled: bool,
pub dom_worklet_timeout_ms: i64,
/// True to compile all WebRender shaders when Servo initializes. This is mostly
/// useful when modifying the shaders, to ensure they all compile after each change is
/// made.
pub gfx_precache_shaders: bool,
/// Whether or not antialiasing is enabled for text rendering.
pub gfx_text_antialiasing_enabled: bool,
/// Whether or not subpixel antialiasing is enabled for text rendering.
pub gfx_subpixel_text_antialiasing_enabled: bool,
pub gfx_texture_swizzling_enabled: bool,
/// Whether or not the DOM inspector should show shadow roots of user-agent shadow trees
pub inspector_show_servo_internal_shadow_roots: bool,
pub js_asmjs_enabled: bool,
pub js_asyncstack: bool,
pub js_baseline_interpreter_enabled: bool,
/// Whether to disable the jit within SpiderMonkey
pub js_disable_jit: bool,
pub js_baseline_jit_enabled: bool,
pub js_baseline_jit_unsafe_eager_compilation_enabled: bool,
pub js_discard_system_source: bool,
pub js_dump_stack_on_debuggee_would_run: bool,
pub js_ion_enabled: bool,
pub js_ion_offthread_compilation_enabled: bool,
pub js_ion_unsafe_eager_compilation_enabled: bool,
pub js_mem_gc_allocation_threshold_mb: i64,
pub js_mem_gc_allocation_threshold_factor: i64,
pub js_mem_gc_allocation_threshold_avoid_interrupt_factor: i64,
pub js_mem_gc_compacting_enabled: bool,
pub js_mem_gc_decommit_threshold_mb: i64,
pub js_mem_gc_dynamic_heap_growth_enabled: bool,
pub js_mem_gc_dynamic_mark_slice_enabled: bool,
pub js_mem_gc_empty_chunk_count_max: i64,
pub js_mem_gc_empty_chunk_count_min: i64,
pub js_mem_gc_high_frequency_heap_growth_max: i64,
pub js_mem_gc_high_frequency_heap_growth_min: i64,
pub js_mem_gc_high_frequency_high_limit_mb: i64,
pub js_mem_gc_high_frequency_low_limit_mb: i64,
pub js_mem_gc_high_frequency_time_limit_ms: i64,
pub js_mem_gc_incremental_enabled: bool,
pub js_mem_gc_incremental_slice_ms: i64,
pub js_mem_gc_low_frequency_heap_growth: i64,
pub js_mem_gc_per_zone_enabled: bool,
pub js_mem_gc_zeal_frequency: i64,
pub js_mem_gc_zeal_level: i64,
pub js_mem_max: i64,
pub js_native_regex_enabled: bool,
pub js_offthread_compilation_enabled: bool,
pub js_parallel_parsing_enabled: bool,
pub js_shared_memory: bool,
pub js_throw_on_asmjs_validation_failure: bool,
pub js_throw_on_debuggee_would_run: bool,
pub js_timers_minimum_duration: i64,
pub js_wasm_baseline_enabled: bool,
pub js_wasm_enabled: bool,
pub js_wasm_ion_enabled: bool,
pub js_werror_enabled: bool,
pub layout_animations_test_enabled: bool,
pub layout_columns_enabled: bool,
pub layout_grid_enabled: bool,
pub layout_container_queries_enabled: bool,
pub layout_css_transition_behavior_enabled: bool,
pub layout_flexbox_enabled: bool,
pub layout_threads: i64,
pub layout_unimplemented: bool,
pub layout_writing_mode_enabled: bool,
/// Enable hardware acceleration for video playback.
pub media_glvideo_enabled: bool,
/// Enable a non-standard event handler for verifying behavior of media elements during tests.
pub media_testing_enabled: bool,
pub network_enforce_tls_enabled: bool,
pub network_enforce_tls_localhost: bool,
pub network_enforce_tls_onion: bool,
pub network_http_cache_disabled: bool,
pub network_local_directory_listing_enabled: bool,
pub network_mime_sniff: bool,
pub session_history_max_length: i64,
/// The background color of shell's viewport. This will be used by OpenGL's `glClearColor`.
pub shell_background_color_rgba: [f64; 4],
pub webgl_testing_context_creation_error: bool,
/// Number of workers per threadpool, if we fail to detect how much
/// parallelism is available at runtime.
pub threadpools_fallback_worker_num: i64,
/// Maximum number of workers for the Image Cache thread pool
pub threadpools_image_cache_workers_max: i64,
/// Maximum number of workers for the Networking async runtime thread pool
pub threadpools_async_runtime_workers_max: i64,
/// Maximum number of workers for the Core Resource Manager
pub threadpools_resource_workers_max: i64,
/// Maximum number of workers for webrender
pub threadpools_webrender_workers_max: i64,
/// The user-agent to use for Servo. This can also be set via [`UserAgentPlatform`] in
/// order to set the value to the default value for the given platform.
pub user_agent: String,
}
impl Preferences {
const fn const_default() -> Self {
Self {
css_animations_testing_enabled: false,
devtools_server_enabled: false,
devtools_server_port: 0,
dom_abort_controller_enabled: false,
dom_allow_scripts_to_close_windows: false,
dom_bluetooth_enabled: false,
dom_bluetooth_testing_enabled: false,
dom_canvas_capture_enabled: false,
dom_canvas_text_enabled: true,
dom_clipboardevent_enabled: true,
dom_composition_event_enabled: false,
dom_crypto_subtle_enabled: true,
dom_customelements_enabled: true,
dom_document_dblclick_dist: 1,
dom_document_dblclick_timeout: 300,
dom_fontface_enabled: false,
dom_forcetouch_enabled: false,
dom_fullscreen_test: false,
dom_gamepad_enabled: true,
dom_imagebitmap_enabled: false,
dom_intersection_observer_enabled: false,
dom_microdata_testing_enabled: false,
dom_mouse_event_which_enabled: false,
dom_mutation_observer_enabled: true,
dom_notification_enabled: false,
dom_offscreen_canvas_enabled: false,
dom_permissions_enabled: false,
dom_permissions_testing_allowed_in_nonsecure_contexts: false,
dom_resize_observer_enabled: false,
dom_script_asynch: true,
dom_serviceworker_enabled: false,
dom_serviceworker_timeout_seconds: 60,
dom_servo_helpers_enabled: false,
dom_servoparser_async_html_tokenizer_enabled: false,
dom_shadowdom_enabled: true,
dom_svg_enabled: false,
dom_testable_crash_enabled: false,
dom_testbinding_enabled: false,
dom_testbinding_prefcontrolled2_enabled: false,
dom_testbinding_prefcontrolled_enabled: false,
dom_testbinding_preference_value_falsy: false,
dom_testbinding_preference_value_quote_string_test: String::new(),
dom_testbinding_preference_value_space_string_test: String::new(),
dom_testbinding_preference_value_string_empty: String::new(),
dom_testbinding_preference_value_string_test: String::new(),
dom_testbinding_preference_value_truthy: false,
dom_testing_element_activation_enabled: false,
dom_testing_html_input_element_select_files_enabled: false,
dom_testperf_enabled: false,
dom_urlpattern_enabled: false,
dom_webgl2_enabled: false,
dom_webgpu_enabled: false,
dom_webgpu_wgpu_backend: String::new(),
dom_webrtc_enabled: false,
dom_webrtc_transceiver_enabled: false,
dom_webvtt_enabled: false,
dom_webxr_enabled: true,
dom_webxr_first_person_observer_view: false,
dom_webxr_glwindow_cubemap: false,
dom_webxr_glwindow_enabled: true,
dom_webxr_glwindow_left_right: false,
dom_webxr_glwindow_red_cyan: false,
dom_webxr_glwindow_spherical: false,
dom_webxr_hands_enabled: true,
dom_webxr_layers_enabled: false,
dom_webxr_openxr_enabled: true,
dom_webxr_sessionavailable: false,
dom_webxr_test: false,
dom_webxr_unsafe_assume_user_intent: false,
dom_worklet_blockingsleep: false,
dom_worklet_enabled: false,
dom_worklet_testing_enabled: false,
dom_worklet_timeout_ms: 10,
dom_xpath_enabled: false,
fonts_default: String::new(),
fonts_default_monospace_size: 13,
fonts_default_size: 16,
fonts_monospace: String::new(),
fonts_sans_serif: String::new(),
fonts_serif: String::new(),
gfx_precache_shaders: false,
gfx_text_antialiasing_enabled: true,
gfx_subpixel_text_antialiasing_enabled: true,
gfx_texture_swizzling_enabled: true,
inspector_show_servo_internal_shadow_roots: false,
js_asmjs_enabled: true,
js_asyncstack: false,
js_baseline_interpreter_enabled: true,
js_baseline_jit_enabled: true,
js_baseline_jit_unsafe_eager_compilation_enabled: false,
js_disable_jit: false,
js_discard_system_source: false,
js_dump_stack_on_debuggee_would_run: false,
js_ion_enabled: true,
js_ion_offthread_compilation_enabled: true,
js_ion_unsafe_eager_compilation_enabled: false,
js_mem_gc_allocation_threshold_avoid_interrupt_factor: 100,
js_mem_gc_allocation_threshold_factor: 100,
js_mem_gc_allocation_threshold_mb: 30,
js_mem_gc_compacting_enabled: true,
js_mem_gc_decommit_threshold_mb: 32,
js_mem_gc_dynamic_heap_growth_enabled: true,
js_mem_gc_dynamic_mark_slice_enabled: true,
js_mem_gc_empty_chunk_count_max: 30,
js_mem_gc_empty_chunk_count_min: 1,
js_mem_gc_high_frequency_heap_growth_max: 300,
js_mem_gc_high_frequency_heap_growth_min: 150,
js_mem_gc_high_frequency_high_limit_mb: 500,
js_mem_gc_high_frequency_low_limit_mb: 100,
js_mem_gc_high_frequency_time_limit_ms: 1000,
js_mem_gc_incremental_enabled: true,
js_mem_gc_incremental_slice_ms: 10,
js_mem_gc_low_frequency_heap_growth: 150,
js_mem_gc_per_zone_enabled: false,
js_mem_gc_zeal_frequency: 100,
js_mem_gc_zeal_level: 0,
js_mem_max: -1,
js_native_regex_enabled: true,
js_offthread_compilation_enabled: true,
js_parallel_parsing_enabled: true,
js_shared_memory: true,
js_throw_on_asmjs_validation_failure: false,
js_throw_on_debuggee_would_run: false,
js_timers_minimum_duration: 1000,
js_wasm_baseline_enabled: true,
js_wasm_enabled: true,
js_wasm_ion_enabled: true,
js_werror_enabled: false,
layout_animations_test_enabled: false,
layout_columns_enabled: false,
layout_container_queries_enabled: false,
layout_css_transition_behavior_enabled: true,
layout_flexbox_enabled: true,
layout_grid_enabled: false,
// TODO(mrobinson): This should likely be based on the number of processors.
layout_threads: 3,
layout_unimplemented: false,
layout_writing_mode_enabled: false,
media_glvideo_enabled: false,
media_testing_enabled: false,
network_enforce_tls_enabled: false,
network_enforce_tls_localhost: false,
network_enforce_tls_onion: false,
network_http_cache_disabled: false,
network_local_directory_listing_enabled: true,
network_mime_sniff: false,
session_history_max_length: 20,
shell_background_color_rgba: [1.0, 1.0, 1.0, 1.0],
threadpools_async_runtime_workers_max: 6,
threadpools_fallback_worker_num: 3,
threadpools_image_cache_workers_max: 4,
threadpools_resource_workers_max: 4,
threadpools_webrender_workers_max: 4,
webgl_testing_context_creation_error: false,
user_agent: String::new(),
}
}
}
impl Default for Preferences {
fn default() -> Self {
let mut preferences = Self::const_default();
preferences.user_agent = UserAgentPlatform::default().to_user_agent_string();
preferences
}
}
pub enum UserAgentPlatform {
Desktop,
Android,
OpenHarmony,
Ios,
}
impl UserAgentPlatform {
/// Return the default `UserAgentPlatform` for this platform. This is
/// not an implementation of `Default` so that it can be `const`.
const fn default() -> Self {
if cfg!(target_os = "android") {
Self::Android
} else if cfg!(target_env = "ohos") {
Self::OpenHarmony
} else if cfg!(target_os = "ios") {
Self::Ios
} else {
Self::Desktop
}
}
}
impl UserAgentPlatform {
/// Convert this [`UserAgentPlatform`] into its corresponding `String` value, ie the
/// default user-agent to use for this platform.
pub fn to_user_agent_string(&self) -> String {
const SERVO_VERSION: &str = env!("CARGO_PKG_VERSION");
match self {
UserAgentPlatform::Desktop
if cfg!(all(target_os = "windows", target_arch = "x86_64")) =>
{
#[cfg(target_arch = "x86_64")]
const ARCHITECTURE: &str = "x86; ";
#[cfg(not(target_arch = "x86_64"))]
const ARCHITECTURE: &str = "";
format!(
"Mozilla/5.0 (Windows NT 10.0; Win64; {ARCHITECTURE}rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
)
},
UserAgentPlatform::Desktop if cfg!(target_os = "macos") => {
format!(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
)
},
UserAgentPlatform::Desktop => {
#[cfg(target_arch = "x86_64")]
const ARCHITECTURE: &str = "x86_64";
// TODO: This is clearly wrong for other platforms.
#[cfg(not(target_arch = "x86_64"))]
const ARCHITECTURE: &str = "i686";
format!(
"Mozilla/5.0 (X11; Linux {ARCHITECTURE}; rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
)
},
UserAgentPlatform::Android => {
format!(
"Mozilla/5.0 (Android; Mobile; rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
)
},
UserAgentPlatform::OpenHarmony => format!(
"Mozilla/5.0 (OpenHarmony; Mobile; rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
),
UserAgentPlatform::Ios => format!(
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X; rv:128.0) Servo/{SERVO_VERSION} Firefox/128.0"
),
}
}
}