servo_config/
opts.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Configuration options for a single run of the servo application. Created
6//! from command line arguments.
7
8use std::default::Default;
9use std::path::PathBuf;
10use std::sync::OnceLock;
11
12use serde::{Deserialize, Serialize};
13use servo_url::ServoUrl;
14
15/// Global flags for Servo, currently set on the command line.
16#[derive(Clone, Debug, Deserialize, Serialize)]
17pub struct Opts {
18    /// `None` to disable the time profiler or `Some` to enable it with:
19    ///
20    ///  - an interval in seconds to cause it to produce output on that interval.
21    ///    (`i.e. -p 5`).
22    ///  - a file path to write profiling info to a TSV file upon Servo's termination.
23    ///    (`i.e. -p out.tsv`).
24    pub time_profiling: Option<OutputOptions>,
25
26    /// When the profiler is enabled, this is an optional path to dump a self-contained HTML file
27    /// visualizing the traces as a timeline.
28    pub time_profiler_trace_path: Option<String>,
29
30    /// True to turn off incremental layout.
31    pub nonincremental_layout: bool,
32
33    pub user_stylesheets: Vec<(Vec<u8>, ServoUrl)>,
34
35    /// True to exit on thread failure instead of displaying about:failure.
36    pub hard_fail: bool,
37
38    /// Debug options that are used by developers to control Servo
39    /// behavior for debugging purposes.
40    pub debug: DiagnosticsLogging,
41
42    /// Whether we're running in multiprocess mode.
43    pub multiprocess: bool,
44
45    /// Whether to force using ipc_channel instead of crossbeam_channel in singleprocess mode. Does
46    /// nothing in multiprocess mode.
47    pub force_ipc: bool,
48
49    /// Whether we want background hang monitor enabled or not
50    pub background_hang_monitor: bool,
51
52    /// Whether we're running inside the sandbox.
53    pub sandbox: bool,
54
55    /// Probability of randomly closing a pipeline,
56    /// used for testing the hardening of the constellation.
57    pub random_pipeline_closure_probability: Option<f32>,
58
59    /// The seed for the RNG used to randomly close pipelines,
60    /// used for testing the hardening of the constellation.
61    pub random_pipeline_closure_seed: Option<usize>,
62
63    /// Load shaders from disk.
64    pub shaders_path: Option<PathBuf>,
65
66    /// Directory for a default config directory
67    pub config_dir: Option<PathBuf>,
68
69    /// Path to PEM encoded SSL CA certificate store.
70    pub certificate_path: Option<String>,
71
72    /// Whether or not to completely ignore SSL certificate validation errors.
73    /// TODO: We should see if we can eliminate the need for this by fixing
74    /// <https://github.com/servo/servo/issues/30080>.
75    pub ignore_certificate_errors: bool,
76
77    /// Unminify Javascript.
78    pub unminify_js: bool,
79
80    /// Directory path that was created with "unminify-js"
81    pub local_script_source: Option<String>,
82
83    /// Unminify Css.
84    pub unminify_css: bool,
85
86    /// Print Progressive Web Metrics to console.
87    pub print_pwm: bool,
88}
89
90/// Debug options for Servo, currently set on the command line with -Z
91#[derive(Clone, Debug, Default, Deserialize, Serialize)]
92pub struct DiagnosticsLogging {
93    /// List all the debug options.
94    pub help: bool,
95
96    /// Print the DOM after each restyle.
97    pub style_tree: bool,
98
99    /// Log the rule tree.
100    pub rule_tree: bool,
101
102    /// Log the fragment tree after each layout.
103    pub flow_tree: bool,
104
105    /// Log the stacking context tree after each layout.
106    pub stacking_context_tree: bool,
107
108    /// Log the scroll tree after each layout.
109    ///
110    /// Displays the hierarchy of scrollable areas and their properties.
111    pub scroll_tree: bool,
112
113    /// Log the display list after each layout.
114    pub display_list: bool,
115
116    /// Log notifications when a relayout occurs.
117    pub relayout_event: bool,
118
119    /// Periodically log on which events script threads spend their processing time.
120    pub profile_script_events: bool,
121
122    /// Log style sharing cache statistics to after each restyle.
123    ///
124    /// Shows hit/miss statistics for the style sharing cache
125    pub style_statistics: bool,
126
127    /// Log garbage collection passes and their durations.
128    pub gc_profile: bool,
129}
130
131impl DiagnosticsLogging {
132    pub fn extend(&mut self, debug_string: String) -> Result<(), String> {
133        for option in debug_string.split(',') {
134            match option {
135                "help" => self.help = true,
136                "display-list" => self.display_list = true,
137                "stacking-context-tree" => self.stacking_context_tree = true,
138                "flow-tree" => self.flow_tree = true,
139                "rule-tree" => self.rule_tree = true,
140                "style-tree" => self.style_tree = true,
141                "style-stats" => self.style_statistics = true,
142                "scroll-tree" => self.scroll_tree = true,
143                "gc-profile" => self.gc_profile = true,
144                "profile-script-events" => self.profile_script_events = true,
145                "relayout-event" => self.relayout_event = true,
146                "" => {},
147                _ => return Err(String::from(option)),
148            };
149        }
150
151        Ok(())
152    }
153}
154
155#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
156pub enum OutputOptions {
157    /// Database connection config (hostname, name, user, pass)
158    FileName(String),
159    Stdout(f64),
160}
161
162impl Default for Opts {
163    fn default() -> Self {
164        Self {
165            time_profiling: None,
166            time_profiler_trace_path: None,
167            nonincremental_layout: false,
168            user_stylesheets: Vec::new(),
169            hard_fail: true,
170            multiprocess: false,
171            force_ipc: false,
172            background_hang_monitor: false,
173            random_pipeline_closure_probability: None,
174            random_pipeline_closure_seed: None,
175            sandbox: false,
176            debug: Default::default(),
177            config_dir: None,
178            shaders_path: None,
179            certificate_path: None,
180            ignore_certificate_errors: false,
181            unminify_js: false,
182            local_script_source: None,
183            unminify_css: false,
184            print_pwm: false,
185        }
186    }
187}
188
189// Make Opts available globally. This saves having to clone and pass
190// opts everywhere it is used, which gets particularly cumbersome
191// when passing through the DOM structures.
192static OPTIONS: OnceLock<Opts> = OnceLock::new();
193
194/// Initialize options.
195///
196/// Should only be called once at process startup.
197/// Must be called before the first call to [get].
198pub fn initialize_options(opts: Opts) {
199    OPTIONS.set(opts).expect("Already initialized");
200}
201
202/// Get the servo options
203///
204/// If the servo options have not been initialized by calling [initialize_options], then the
205/// options will be initialized to default values. Outside of tests the options should
206/// be explicitly initialized.
207#[inline]
208pub fn get() -> &'static Opts {
209    // In unit-tests using default options reduces boilerplate.
210    // We can't use `cfg(test)` since that only is enabled when this crate
211    // is compiled in test mode.
212    // We rely on the `expect` in `initialize_options` to inform us if refactoring
213    // causes a `get` call to move before `initialize_options`.
214    OPTIONS.get_or_init(Default::default)
215}