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    /// Whether or not Servo should wait for web content to go into an idle state, therefore
19    /// likely producing a stable output image. This is useful for taking screenshots of pages
20    /// after they have loaded.
21    pub wait_for_stable_image: bool,
22
23    /// `None` to disable the time profiler or `Some` to enable it with:
24    ///
25    ///  - an interval in seconds to cause it to produce output on that interval.
26    ///    (`i.e. -p 5`).
27    ///  - a file path to write profiling info to a TSV file upon Servo's termination.
28    ///    (`i.e. -p out.tsv`).
29    pub time_profiling: Option<OutputOptions>,
30
31    /// When the profiler is enabled, this is an optional path to dump a self-contained HTML file
32    /// visualizing the traces as a timeline.
33    pub time_profiler_trace_path: Option<String>,
34
35    /// True to turn off incremental layout.
36    pub nonincremental_layout: bool,
37
38    pub user_stylesheets: Vec<(Vec<u8>, ServoUrl)>,
39
40    /// True to exit on thread failure instead of displaying about:failure.
41    pub hard_fail: bool,
42
43    /// Debug options that are used by developers to control Servo
44    /// behavior for debugging purposes.
45    pub debug: DebugOptions,
46
47    /// Whether we're running in multiprocess mode.
48    pub multiprocess: bool,
49
50    /// Whether to force using ipc_channel instead of crossbeam_channel in singleprocess mode. Does
51    /// nothing in multiprocess mode.
52    pub force_ipc: bool,
53
54    /// Whether we want background hang monitor enabled or not
55    pub background_hang_monitor: bool,
56
57    /// Whether we're running inside the sandbox.
58    pub sandbox: bool,
59
60    /// Probability of randomly closing a pipeline,
61    /// used for testing the hardening of the constellation.
62    pub random_pipeline_closure_probability: Option<f32>,
63
64    /// The seed for the RNG used to randomly close pipelines,
65    /// used for testing the hardening of the constellation.
66    pub random_pipeline_closure_seed: Option<usize>,
67
68    /// Load shaders from disk.
69    pub shaders_dir: Option<PathBuf>,
70
71    /// Directory for a default config directory
72    pub config_dir: Option<PathBuf>,
73
74    /// Path to PEM encoded SSL CA certificate store.
75    pub certificate_path: Option<String>,
76
77    /// Whether or not to completely ignore SSL certificate validation errors.
78    /// TODO: We should see if we can eliminate the need for this by fixing
79    /// <https://github.com/servo/servo/issues/30080>.
80    pub ignore_certificate_errors: bool,
81
82    /// Unminify Javascript.
83    pub unminify_js: bool,
84
85    /// Directory path that was created with "unminify-js"
86    pub local_script_source: Option<String>,
87
88    /// Unminify Css.
89    pub unminify_css: bool,
90
91    /// Print Progressive Web Metrics to console.
92    pub print_pwm: bool,
93}
94
95/// Debug options for Servo, currently set on the command line with -Z
96#[derive(Clone, Debug, Default, Deserialize, Serialize)]
97pub struct DebugOptions {
98    /// List all the debug options.
99    pub help: bool,
100
101    /// Print the DOM after each restyle.
102    pub dump_style_tree: bool,
103
104    /// Dumps the rule tree.
105    pub dump_rule_tree: bool,
106
107    /// Print the fragment tree after each layout.
108    pub dump_flow_tree: bool,
109
110    /// Print the stacking context tree after each layout.
111    pub dump_stacking_context_tree: bool,
112
113    /// Print the scroll tree after each layout.
114    pub dump_scroll_tree: bool,
115
116    /// Print the display list after each layout.
117    pub dump_display_list: bool,
118
119    /// Print notifications when there is a relayout.
120    pub relayout_event: bool,
121
122    /// Periodically print out on which events script threads spend their processing time.
123    pub profile_script_events: bool,
124
125    /// True if each step of layout is traced to an external JSON file
126    /// for debugging purposes. Setting this implies sequential layout
127    /// and paint.
128    pub trace_layout: bool,
129
130    /// Disable the style sharing cache.
131    pub disable_share_style_cache: bool,
132
133    /// Whether to show in stdout style sharing cache stats after a restyle.
134    pub dump_style_statistics: bool,
135
136    /// Translate mouse input into touch events.
137    pub convert_mouse_to_touch: bool,
138
139    /// Log GC passes and their durations.
140    pub gc_profile: bool,
141
142    /// Show webrender profiling stats on screen.
143    pub webrender_stats: bool,
144
145    /// True to use OS native signposting facilities. This makes profiling events (script activity,
146    /// reflow, compositing, etc.) appear in Instruments.app on macOS.
147    pub signpost: bool,
148}
149
150impl DebugOptions {
151    pub fn extend(&mut self, debug_string: String) -> Result<(), String> {
152        for option in debug_string.split(',') {
153            match option {
154                "help" => self.help = true,
155                "convert-mouse-to-touch" => self.convert_mouse_to_touch = true,
156                "disable-share-style-cache" => self.disable_share_style_cache = true,
157                "dump-display-list" => self.dump_display_list = true,
158                "dump-stacking-context-tree" => self.dump_stacking_context_tree = true,
159                "dump-flow-tree" => self.dump_flow_tree = true,
160                "dump-rule-tree" => self.dump_rule_tree = true,
161                "dump-style-tree" => self.dump_style_tree = true,
162                "dump-scroll-tree" => self.dump_scroll_tree = true,
163                "gc-profile" => self.gc_profile = true,
164                "profile-script-events" => self.profile_script_events = true,
165                "relayout-event" => self.relayout_event = true,
166                "signpost" => self.signpost = true,
167                "dump-style-stats" => self.dump_style_statistics = true,
168                "trace-layout" => self.trace_layout = true,
169                "wr-stats" => self.webrender_stats = true,
170                "" => {},
171                _ => return Err(String::from(option)),
172            };
173        }
174
175        Ok(())
176    }
177}
178
179#[derive(Clone, Debug, Deserialize, Serialize)]
180pub enum OutputOptions {
181    /// Database connection config (hostname, name, user, pass)
182    FileName(String),
183    Stdout(f64),
184}
185
186impl Default for Opts {
187    fn default() -> Self {
188        Self {
189            wait_for_stable_image: false,
190            time_profiling: None,
191            time_profiler_trace_path: None,
192            nonincremental_layout: false,
193            user_stylesheets: Vec::new(),
194            hard_fail: true,
195            multiprocess: false,
196            force_ipc: false,
197            background_hang_monitor: false,
198            random_pipeline_closure_probability: None,
199            random_pipeline_closure_seed: None,
200            sandbox: false,
201            debug: Default::default(),
202            config_dir: None,
203            shaders_dir: None,
204            certificate_path: None,
205            ignore_certificate_errors: false,
206            unminify_js: false,
207            local_script_source: None,
208            unminify_css: false,
209            print_pwm: false,
210        }
211    }
212}
213
214// Make Opts available globally. This saves having to clone and pass
215// opts everywhere it is used, which gets particularly cumbersome
216// when passing through the DOM structures.
217static OPTIONS: OnceLock<Opts> = OnceLock::new();
218
219/// Initialize options.
220///
221/// Should only be called once at process startup.
222/// Must be called before the first call to [get].
223pub fn initialize_options(opts: Opts) {
224    OPTIONS.set(opts).expect("Already initialized");
225}
226
227/// Get the servo options
228///
229/// If the servo options have not been initialized by calling [initialize_options], then the
230/// options will be initialized to default values. Outside of tests the options should
231/// be explicitly initialized.
232#[inline]
233pub fn get() -> &'static Opts {
234    // In unit-tests using default options reduces boilerplate.
235    // We can't use `cfg(test)` since that only is enabled when this crate
236    // is compiled in test mode.
237    // We rely on the `expect` in `initialize_options` to inform us if refactoring
238    // causes a `get` call to move before `initialize_options`.
239    OPTIONS.get_or_init(Default::default)
240}