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 /// Disable the style sharing cache.
126 pub disable_share_style_cache: bool,
127
128 /// Whether to show in stdout style sharing cache stats after a restyle.
129 pub dump_style_statistics: bool,
130
131 /// Translate mouse input into touch events.
132 pub convert_mouse_to_touch: bool,
133
134 /// Log GC passes and their durations.
135 pub gc_profile: bool,
136}
137
138impl DebugOptions {
139 pub fn extend(&mut self, debug_string: String) -> Result<(), String> {
140 for option in debug_string.split(',') {
141 match option {
142 "help" => self.help = true,
143 "convert-mouse-to-touch" => self.convert_mouse_to_touch = true,
144 "disable-share-style-cache" => self.disable_share_style_cache = true,
145 "dump-display-list" => self.dump_display_list = true,
146 "dump-stacking-context-tree" => self.dump_stacking_context_tree = true,
147 "dump-flow-tree" => self.dump_flow_tree = true,
148 "dump-rule-tree" => self.dump_rule_tree = true,
149 "dump-style-tree" => self.dump_style_tree = true,
150 "dump-style-stats" => self.dump_style_statistics = true,
151 "dump-scroll-tree" => self.dump_scroll_tree = true,
152 "gc-profile" => self.gc_profile = true,
153 "profile-script-events" => self.profile_script_events = true,
154 "relayout-event" => self.relayout_event = true,
155 "" => {},
156 _ => return Err(String::from(option)),
157 };
158 }
159
160 Ok(())
161 }
162}
163
164#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
165pub enum OutputOptions {
166 /// Database connection config (hostname, name, user, pass)
167 FileName(String),
168 Stdout(f64),
169}
170
171impl Default for Opts {
172 fn default() -> Self {
173 Self {
174 wait_for_stable_image: false,
175 time_profiling: None,
176 time_profiler_trace_path: None,
177 nonincremental_layout: false,
178 user_stylesheets: Vec::new(),
179 hard_fail: true,
180 multiprocess: false,
181 force_ipc: false,
182 background_hang_monitor: false,
183 random_pipeline_closure_probability: None,
184 random_pipeline_closure_seed: None,
185 sandbox: false,
186 debug: Default::default(),
187 config_dir: None,
188 shaders_dir: None,
189 certificate_path: None,
190 ignore_certificate_errors: false,
191 unminify_js: false,
192 local_script_source: None,
193 unminify_css: false,
194 print_pwm: false,
195 }
196 }
197}
198
199// Make Opts available globally. This saves having to clone and pass
200// opts everywhere it is used, which gets particularly cumbersome
201// when passing through the DOM structures.
202static OPTIONS: OnceLock<Opts> = OnceLock::new();
203
204/// Initialize options.
205///
206/// Should only be called once at process startup.
207/// Must be called before the first call to [get].
208pub fn initialize_options(opts: Opts) {
209 OPTIONS.set(opts).expect("Already initialized");
210}
211
212/// Get the servo options
213///
214/// If the servo options have not been initialized by calling [initialize_options], then the
215/// options will be initialized to default values. Outside of tests the options should
216/// be explicitly initialized.
217#[inline]
218pub fn get() -> &'static Opts {
219 // In unit-tests using default options reduces boilerplate.
220 // We can't use `cfg(test)` since that only is enabled when this crate
221 // is compiled in test mode.
222 // We rely on the `expect` in `initialize_options` to inform us if refactoring
223 // causes a `get` call to move before `initialize_options`.
224 OPTIONS.get_or_init(Default::default)
225}