servoshell: Support runtime preference manipulation (#38159)

These changes add a custom servo:preferences URL that allows modifying
selected preferences at runtime. The goal of this work is to make it
easy to test pages while toggling experimental web platform features,
and support quickly changing the User-Agent header.

Testing: Manually verified that spacex.com loads correctly after
changing the user agent, and that https://polygon.io/ displays grid
elements correctly and no console errors with the experimental prefs
enabled.
Fixes: #35862

<img width="1136" height="880" alt="Screenshot 2025-07-18 at 1 06 23 AM"
src="https://github.com/user-attachments/assets/2d27c321-6ca0-43c3-a347-7bc4b55272df"
/>

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-08-30 12:51:58 -04:00 committed by GitHub
parent c97ec1b2fb
commit 6565d982bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 308 additions and 25 deletions

View file

@ -482,6 +482,9 @@ pub struct Constellation<STF, SWF> {
/// When in single-process mode, join handles for script-threads.
script_join_handles: HashMap<WebViewId, JoinHandle<()>>,
/// A list of URLs that can access privileged internal APIs.
privileged_urls: Vec<ServoUrl>,
}
/// State needed to construct a constellation.
@ -535,6 +538,9 @@ pub struct InitialConstellationState {
/// User content manager
pub user_content_manager: UserContentManager,
/// A list of URLs that can access privileged internal APIs.
pub privileged_urls: Vec<ServoUrl>,
/// The async runtime.
pub async_runtime: Box<dyn AsyncRuntime>,
}
@ -732,6 +738,7 @@ where
process_manager: ProcessManager::new(state.mem_profiler_chan),
async_runtime: state.async_runtime,
script_join_handles: Default::default(),
privileged_urls: state.privileged_urls,
};
constellation.run();
@ -1003,6 +1010,7 @@ where
player_context: WindowGLContext::get(),
rippy_data: self.rippy_data.clone(),
user_content_manager: self.user_content_manager.clone(),
privileged_urls: self.privileged_urls.clone(),
});
let pipeline = match result {

View file

@ -204,6 +204,9 @@ pub struct InitialPipelineState {
/// User content manager
pub user_content_manager: UserContentManager,
/// A list of URLs that can access privileged internal APIs.
pub privileged_urls: Vec<ServoUrl>,
}
pub struct NewPipeline {
@ -305,6 +308,7 @@ impl Pipeline {
rippy_data: state.rippy_data,
user_content_manager: state.user_content_manager,
lifeline_sender: None,
privileged_urls: state.privileged_urls,
};
// Spawn the child process.
@ -497,6 +501,7 @@ pub struct UnprivilegedPipelineContent {
rippy_data: Vec<u8>,
user_content_manager: UserContentManager,
lifeline_sender: Option<IpcSender<()>>,
privileged_urls: Vec<ServoUrl>,
}
impl UnprivilegedPipelineContent {
@ -543,6 +548,7 @@ impl UnprivilegedPipelineContent {
player_context: self.player_context.clone(),
inherited_secure_context: self.load_data.inherited_secure_context,
user_content_manager: self.user_content_manager,
privileged_urls: self.privileged_urls,
},
layout_factory,
Arc::new(self.system_font_service.to_proxy()),