From 8432a21d638a7501d36eca00b2a4320bd3ba20fa Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 12 Mar 2026 11:28:02 +0100 Subject: [PATCH] prefs: Move `Opts::user_stylesheets` to `ServoShellPreferences` (#43206) This concept does not need to be exposed to `Opts` any longer as it just controls how servoshell uses the `WebView` API. Testing: A successful compilation is enough here as this is just moving an option. Fixes: This is part of #34967. Signed-off-by: Martin Robinson --- components/config/opts.rs | 4 --- ports/servoshell/desktop/app.rs | 7 ++--- ports/servoshell/prefs.rs | 47 +++++++++++++++++---------------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/components/config/opts.rs b/components/config/opts.rs index 57577cb009b..ef754341a34 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -11,7 +11,6 @@ use std::process; use std::sync::OnceLock; use serde::{Deserialize, Serialize}; -use servo_url::ServoUrl; /// Global flags for Servo, currently set on the command line. #[derive(Clone, Debug, Deserialize, Serialize)] @@ -31,8 +30,6 @@ pub struct Opts { /// True to turn off incremental layout. pub nonincremental_layout: bool, - pub user_stylesheets: Vec<(Vec, ServoUrl)>, - /// True to exit on thread failure instead of displaying about:failure. pub hard_fail: bool, @@ -219,7 +216,6 @@ impl Default for Opts { time_profiling: None, time_profiler_trace_path: None, nonincremental_layout: false, - user_stylesheets: Vec::new(), hard_fail: true, multiprocess: false, force_ipc: false, diff --git a/ports/servoshell/desktop/app.rs b/ports/servoshell/desktop/app.rs index f413edd5dd3..643c0b2ec52 100644 --- a/ports/servoshell/desktop/app.rs +++ b/ports/servoshell/desktop/app.rs @@ -10,7 +10,6 @@ use std::time::Instant; use std::{env, fs}; use servo::protocol_handler::ProtocolRegistry; -use servo::user_contents::UserStyleSheet; use servo::{ EventLoopWaker, Opts, Preferences, ServoBuilder, ServoUrl, UserContentManager, UserScript, }; @@ -120,10 +119,8 @@ impl App { user_content_manager.add_script(Rc::new(script)); } - for (contents, url) in &self.opts.user_stylesheets { - let contents = String::try_from(contents.clone()).unwrap(); - let user_stylesheet = UserStyleSheet::new(contents, url.clone().into_url()); - user_content_manager.add_stylesheet(Rc::new(user_stylesheet)); + for user_stylesheet in &self.servoshell_preferences.user_stylesheets { + user_content_manager.add_stylesheet(user_stylesheet.clone()); } let running_state = Rc::new(RunningAppState::new( diff --git a/ports/servoshell/prefs.rs b/ports/servoshell/prefs.rs index f63e5ae01b5..e0cead80e2a 100644 --- a/ports/servoshell/prefs.rs +++ b/ports/servoshell/prefs.rs @@ -5,9 +5,9 @@ use core::panic; use std::cell::Cell; use std::collections::HashMap; -use std::fs::{self, File, read_to_string}; -use std::io::Read; +use std::fs::{self, read_to_string}; use std::path::{Path, PathBuf}; +use std::rc::Rc; use std::str::FromStr; #[cfg(any(target_os = "android", target_env = "ohos"))] use std::sync::OnceLock; @@ -17,9 +17,9 @@ use bpaf::*; use euclid::Size2D; use log::warn; use serde_json::Value; +use servo::user_contents::UserStyleSheet; use servo::{ DeviceIndependentPixel, DiagnosticsLogging, Opts, OutputOptions, PrefValue, Preferences, - ServoUrl, }; use url::Url; @@ -81,6 +81,8 @@ pub(crate) struct ServoShellPreferences { /// Where to load userscripts from, if any. /// and if the option isn't passed userscripts won't be loaded. pub userscripts_directory: Option, + /// A set of [`UserStylesheets`] to load for content. + pub user_stylesheets: Vec>, /// `None` to disable WebDriver or `Some` with a port number to start a server to listen to /// remote WebDriver commands. pub webdriver_port: Cell>, @@ -112,6 +114,7 @@ impl Default for ServoShellPreferences { output_image_path: None, exit_after_stable_image: false, userscripts_directory: None, + user_stylesheets: Default::default(), webdriver_port: Cell::new(None), #[cfg(target_env = "ohos")] log_filter: None, @@ -266,22 +269,18 @@ fn parse_resolution_string( } } -/// Parse stylesheets into the byte stream. -fn parse_user_stylesheets(string: String) -> Result, ServoUrl)>, std::io::Error> { - Ok(string - .split_whitespace() - .map(|filename| { - let cwd = env::current_dir().unwrap(); - let path = cwd.join(filename); - let url = ServoUrl::from_url(Url::from_file_path(&path).unwrap()); - let mut contents = Vec::new(); - File::open(path) - .unwrap() - .read_to_end(&mut contents) - .unwrap(); - (contents, url) - }) - .collect()) +/// Parse a space or comma-separated list of stylesheet paths into a vector of +/// [`UserStyleSheet`]. +fn parse_user_stylesheets(string: String) -> Result>, std::io::Error> { + let mut results = Vec::new(); + for path_string in string.split([' ', ',']) { + let path = env::current_dir()?.join(path_string); + results.push(Rc::new(UserStyleSheet::new( + read_to_string(&path)?, + Url::from_file_path(&path).unwrap(), + ))); + } + Ok(results) } /// This is a helper function that fulfills the following parsing task @@ -548,9 +547,11 @@ struct CmdArgs { userscripts: Option, /// - /// A user stylesheet to be added to every document. - #[bpaf(argument::("file.css"), parse(parse_user_stylesheets), fallback(vec![]))] - user_stylesheet: Vec<(Vec, ServoUrl)>, + /// Add each of the given UTF-8 encoded CSS files in the space or comma-separated + /// list as user stylesheet to apply to every page loaded. + #[bpaf(argument::("file.css"), parse(parse_user_stylesheets), + fallback(vec![]))] + user_stylesheet: Vec>, /// Start remote WebDriver server on port. #[bpaf(external)] @@ -694,6 +695,7 @@ fn parse_arguments_helper(args_without_binary: Args) -> ArgumentParsingResult { output_image_path: cmd_args.output.map(|p| p.to_string_lossy().into_owned()), exit_after_stable_image: cmd_args.exit, userscripts_directory: cmd_args.userscripts, + user_stylesheets: cmd_args.user_stylesheet, experimental_preferences_enabled: cmd_args.enable_experimental_web_platform_features, #[cfg(target_env = "ohos")] log_filter: cmd_args.log_filter.or_else(|| { @@ -721,7 +723,6 @@ fn parse_arguments_helper(args_without_binary: Args) -> ArgumentParsingResult { .profiler_trace_path .map(|p| p.to_string_lossy().into_owned()), nonincremental_layout: cmd_args.nonincremental_layout, - user_stylesheets: cmd_args.user_stylesheet, hard_fail: cmd_args.hard_fail, multiprocess: cmd_args.multiprocess, background_hang_monitor: cmd_args.background_hang_monitor,