Support isSecureContext for custom protocols

Signed-off-by: Tony <legendmastertony@gmail.com>
This commit is contained in:
Tony 2025-04-25 22:01:08 +08:00
parent 894fbd003d
commit d49689bf09
No known key found for this signature in database
GPG key ID: 34BDD3EA27824956
13 changed files with 103 additions and 10 deletions

View file

@ -142,10 +142,11 @@ use keyboard_types::webdriver::Event as WebDriverInputEvent;
use keyboard_types::{Key, KeyState, KeyboardEvent, Modifiers}; use keyboard_types::{Key, KeyState, KeyboardEvent, Modifiers};
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use media::WindowGLContext; use media::WindowGLContext;
use net::protocols::ProtocolRegistry;
use net_traits::pub_domains::reg_host; use net_traits::pub_domains::reg_host;
use net_traits::request::Referrer; use net_traits::request::Referrer;
use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use net_traits::storage_thread::{StorageThreadMsg, StorageType};
use net_traits::{self, IpcSend, ReferrerPolicy, ResourceThreads}; use net_traits::{self, IpcSend, Protocol, Protocols, ReferrerPolicy, ResourceThreads};
use profile_traits::{mem, time}; use profile_traits::{mem, time};
use script_layout_interface::{LayoutFactory, ScriptThreadFactory}; use script_layout_interface::{LayoutFactory, ScriptThreadFactory};
use script_traits::{ use script_traits::{
@ -474,6 +475,9 @@ pub struct Constellation<STF, SWF> {
/// The process manager. /// The process manager.
process_manager: ProcessManager, process_manager: ProcessManager,
/// Registered custom protocols
pub protocols: Arc<ProtocolRegistry>,
} }
/// State needed to construct a constellation. /// State needed to construct a constellation.
@ -526,6 +530,9 @@ pub struct InitialConstellationState {
/// User content manager /// User content manager
pub user_content_manager: UserContentManager, pub user_content_manager: UserContentManager,
/// Registered custom protocols
pub protocols: Arc<ProtocolRegistry>,
} }
/// Data needed for webdriver /// Data needed for webdriver
@ -741,6 +748,7 @@ where
rippy_data, rippy_data,
user_content_manager: state.user_content_manager, user_content_manager: state.user_content_manager,
process_manager: ProcessManager::new(state.mem_profiler_chan), process_manager: ProcessManager::new(state.mem_profiler_chan),
protocols: state.protocols,
}; };
constellation.run(); constellation.run();
@ -980,6 +988,19 @@ where
player_context: WindowGLContext::get(), player_context: WindowGLContext::get(),
rippy_data: self.rippy_data.clone(), rippy_data: self.rippy_data.clone(),
user_content_manager: self.user_content_manager.clone(), user_content_manager: self.user_content_manager.clone(),
protocols: Protocols::new(
self.protocols
.iter()
.map(|(protocol, handler)| {
(
protocol.to_string(),
Protocol {
is_secure: handler.is_secure(),
},
)
})
.collect(),
),
}); });
let pipeline = match result { let pipeline = match result {

View file

@ -33,8 +33,8 @@ use ipc_channel::router::ROUTER;
use log::{debug, error, warn}; use log::{debug, error, warn};
use media::WindowGLContext; use media::WindowGLContext;
use net::image_cache::ImageCacheImpl; use net::image_cache::ImageCacheImpl;
use net_traits::ResourceThreads;
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use net_traits::{Protocols, ResourceThreads};
use profile::system_reporter; use profile::system_reporter;
use profile_traits::mem::{ProfilerMsg, Reporter}; use profile_traits::mem::{ProfilerMsg, Reporter};
use profile_traits::{mem as profile_mem, time}; use profile_traits::{mem as profile_mem, time};
@ -197,6 +197,9 @@ pub struct InitialPipelineState {
/// User content manager /// User content manager
pub user_content_manager: UserContentManager, pub user_content_manager: UserContentManager,
/// Registered custom protocols
pub protocols: Protocols,
} }
pub struct NewPipeline { pub struct NewPipeline {
@ -294,6 +297,7 @@ impl Pipeline {
rippy_data: state.rippy_data, rippy_data: state.rippy_data,
user_content_manager: state.user_content_manager, user_content_manager: state.user_content_manager,
lifeline_sender: None, lifeline_sender: None,
protocols: state.protocols,
}; };
// Spawn the child process. // Spawn the child process.
@ -503,6 +507,7 @@ pub struct UnprivilegedPipelineContent {
player_context: WindowGLContext, player_context: WindowGLContext,
rippy_data: Vec<u8>, rippy_data: Vec<u8>,
user_content_manager: UserContentManager, user_content_manager: UserContentManager,
protocols: Protocols,
lifeline_sender: Option<IpcSender<()>>, lifeline_sender: Option<IpcSender<()>>,
} }
@ -549,6 +554,7 @@ impl UnprivilegedPipelineContent {
player_context: self.player_context.clone(), player_context: self.player_context.clone(),
inherited_secure_context: self.load_data.inherited_secure_context, inherited_secure_context: self.load_data.inherited_secure_context,
user_content_manager: self.user_content_manager, user_content_manager: self.user_content_manager,
protocols: self.protocols.clone(),
}, },
layout_factory, layout_factory,
Arc::new(self.system_font_service.to_proxy()), Arc::new(self.system_font_service.to_proxy()),

View file

@ -110,6 +110,10 @@ impl ProtocolRegistry {
self.handlers.get(scheme).map(|e| e.as_ref()) self.handlers.get(scheme).map(|e| e.as_ref())
} }
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, String, Box<dyn ProtocolHandler>> {
self.handlers.iter()
}
pub fn merge(&mut self, mut other: ProtocolRegistry) { pub fn merge(&mut self, mut other: ProtocolRegistry) {
for (scheme, handler) in other.handlers.drain() { for (scheme, handler) in other.handlers.drain() {
if FORBIDDEN_SCHEMES.contains(&scheme.as_str()) { if FORBIDDEN_SCHEMES.contains(&scheme.as_str()) {

View file

@ -68,6 +68,7 @@ impl DissimilarOriginWindow {
global_to_clone_from.wgpu_id_hub(), global_to_clone_from.wgpu_id_hub(),
Some(global_to_clone_from.is_secure_context()), Some(global_to_clone_from.is_secure_context()),
false, false,
global_to_clone_from.registered_protocols().clone(),
), ),
window_proxy: Dom::from_ref(window_proxy), window_proxy: Dom::from_ref(window_proxy),
location: Default::default(), location: Default::default(),

View file

@ -57,7 +57,7 @@ use net_traits::policy_container::PolicyContainer;
use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBuilder}; use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBuilder};
use net_traits::response::HttpsState; use net_traits::response::HttpsState;
use net_traits::{ use net_traits::{
CoreResourceMsg, CoreResourceThread, FetchResponseListener, IpcSend, ReferrerPolicy, CoreResourceMsg, CoreResourceThread, FetchResponseListener, IpcSend, Protocols, ReferrerPolicy,
ResourceThreads, fetch_async, ResourceThreads, fetch_async,
}; };
use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_time}; use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_time};
@ -376,6 +376,11 @@ pub(crate) struct GlobalScope {
#[ignore_malloc_size_of = "Rc<T> is hard"] #[ignore_malloc_size_of = "Rc<T> is hard"]
notification_permission_request_callback_map: notification_permission_request_callback_map:
DomRefCell<HashMap<String, Rc<NotificationPermissionCallback>>>, DomRefCell<HashMap<String, Rc<NotificationPermissionCallback>>>,
/// Registered custom protocols
#[no_trace]
#[ignore_malloc_size_of = "Arc"]
protocols: Arc<Protocols>,
} }
/// A wrapper for glue-code between the ipc router and the event-loop. /// A wrapper for glue-code between the ipc router and the event-loop.
@ -731,6 +736,7 @@ impl GlobalScope {
#[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>, #[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>,
inherited_secure_context: Option<bool>, inherited_secure_context: Option<bool>,
unminify_js: bool, unminify_js: bool,
protocols: Arc<Protocols>,
) -> Self { ) -> Self {
Self { Self {
task_manager: Default::default(), task_manager: Default::default(),
@ -775,6 +781,7 @@ impl GlobalScope {
byte_length_queuing_strategy_size_function: OnceCell::new(), byte_length_queuing_strategy_size_function: OnceCell::new(),
count_queuing_strategy_size_function: OnceCell::new(), count_queuing_strategy_size_function: OnceCell::new(),
notification_permission_request_callback_map: Default::default(), notification_permission_request_callback_map: Default::default(),
protocols,
} }
} }
@ -2383,6 +2390,11 @@ impl GlobalScope {
&self.creation_url &self.creation_url
} }
/// Get registered custom protocols
pub(crate) fn registered_protocols(&self) -> &Arc<Protocols> {
&self.protocols
}
pub(crate) fn image_cache(&self) -> Arc<dyn ImageCache> { pub(crate) fn image_cache(&self) -> Arc<dyn ImageCache> {
if let Some(window) = self.downcast::<Window>() { if let Some(window) = self.downcast::<Window>() {
return window.image_cache(); return window.image_cache();
@ -3098,7 +3110,7 @@ impl GlobalScope {
if creation_url.scheme() == "blob" && Some(true) == self.inherited_secure_context { if creation_url.scheme() == "blob" && Some(true) == self.inherited_secure_context {
return true; return true;
} }
return creation_url.is_potentially_trustworthy(); return self.protocols.is_url_potentially_trustworthy(creation_url);
} }
false false
} }

View file

@ -52,11 +52,11 @@ use js::rust::{
}; };
use malloc_size_of::MallocSizeOf; use malloc_size_of::MallocSizeOf;
use media::WindowGLContext; use media::WindowGLContext;
use net_traits::ResourceThreads;
use net_traits::image_cache::{ use net_traits::image_cache::{
ImageCache, ImageResponder, ImageResponse, PendingImageId, PendingImageResponse, ImageCache, ImageResponder, ImageResponse, PendingImageId, PendingImageResponse,
}; };
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{Protocols, ResourceThreads};
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use profile_traits::ipc as ProfiledIpc; use profile_traits::ipc as ProfiledIpc;
use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::mem::ProfilerChan as MemProfilerChan;
@ -2834,6 +2834,7 @@ impl Window {
player_context: WindowGLContext, player_context: WindowGLContext,
#[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>, #[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>,
inherited_secure_context: Option<bool>, inherited_secure_context: Option<bool>,
protocols: Arc<Protocols>,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let error_reporter = CSSErrorReporter { let error_reporter = CSSErrorReporter {
pipelineid: pipeline_id, pipelineid: pipeline_id,
@ -2861,6 +2862,7 @@ impl Window {
gpu_id_hub, gpu_id_hub,
inherited_secure_context, inherited_secure_context,
unminify_js, unminify_js,
protocols,
), ),
script_chan, script_chan,
layout: RefCell::new(layout), layout: RefCell::new(layout),

View file

@ -83,6 +83,7 @@ pub(crate) fn prepare_workerscope_init(
origin: global.origin().immutable().clone(), origin: global.origin().immutable().clone(),
creation_url: global.creation_url().clone(), creation_url: global.creation_url().clone(),
inherited_secure_context: Some(global.is_secure_context()), inherited_secure_context: Some(global.is_secure_context()),
protocols: global.registered_protocols().clone(),
}; };
init init
@ -155,6 +156,7 @@ impl WorkerGlobalScope {
Some(..) => Some(devtools_receiver), Some(..) => Some(devtools_receiver),
None => None, None => None,
}; };
let protocols = init.protocols;
Self { Self {
globalscope: GlobalScope::new_inherited( globalscope: GlobalScope::new_inherited(
@ -171,6 +173,7 @@ impl WorkerGlobalScope {
gpu_id_hub, gpu_id_hub,
init.inherited_secure_context, init.inherited_secure_context,
false, false,
protocols,
), ),
worker_id: init.worker_id, worker_id: init.worker_id,
worker_name, worker_name,

View file

@ -12,8 +12,8 @@ use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::Runtime; use js::rust::Runtime;
use net_traits::ResourceThreads;
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use net_traits::{Protocols, ResourceThreads};
use profile_traits::{mem, time}; use profile_traits::{mem, time};
use script_bindings::realms::InRealm; use script_bindings::realms::InRealm;
use script_traits::Painter; use script_traits::Painter;
@ -108,6 +108,7 @@ impl WorkletGlobalScope {
init.gpu_id_hub.clone(), init.gpu_id_hub.clone(),
init.inherited_secure_context, init.inherited_secure_context,
false, false,
init.protocols.clone(),
), ),
base_url, base_url,
to_script_thread_sender: init.to_script_thread_sender.clone(), to_script_thread_sender: init.to_script_thread_sender.clone(),
@ -197,6 +198,8 @@ pub(crate) struct WorkletGlobalScopeInit {
pub(crate) gpu_id_hub: Arc<IdentityHub>, pub(crate) gpu_id_hub: Arc<IdentityHub>,
/// Is considered secure /// Is considered secure
pub(crate) inherited_secure_context: Option<bool>, pub(crate) inherited_secure_context: Option<bool>,
/// Registered custom protocols
pub(crate) protocols: Arc<Protocols>,
} }
/// <https://drafts.css-houdini.org/worklets/#worklet-global-scope-type> /// <https://drafts.css-houdini.org/worklets/#worklet-global-scope-type>

View file

@ -75,7 +75,7 @@ use net_traits::request::{Referrer, RequestId};
use net_traits::response::ResponseInit; use net_traits::response::ResponseInit;
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, FetchResponseMsg, Metadata, NetworkError, FetchMetadata, FetchResponseListener, FetchResponseMsg, Metadata, NetworkError, Protocols,
ResourceFetchTiming, ResourceThreads, ResourceTimingType, ResourceFetchTiming, ResourceThreads, ResourceTimingType,
}; };
use percent_encoding::percent_decode; use percent_encoding::percent_decode;
@ -335,6 +335,10 @@ pub struct ScriptThread {
// In future, this shall be mouse_down_point for primary button // In future, this shall be mouse_down_point for primary button
#[no_trace] #[no_trace]
relative_mouse_down_point: Cell<Point2D<f32, DevicePixel>>, relative_mouse_down_point: Cell<Point2D<f32, DevicePixel>>,
/// Registered custom protocols
#[no_trace]
protocols: Arc<Protocols>,
} }
struct BHMExitSignal { struct BHMExitSignal {
@ -744,6 +748,7 @@ impl ScriptThread {
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
gpu_id_hub: script_thread.gpu_id_hub.clone(), gpu_id_hub: script_thread.gpu_id_hub.clone(),
inherited_secure_context: script_thread.inherited_secure_context, inherited_secure_context: script_thread.inherited_secure_context,
protocols: script_thread.protocols.clone(),
}; };
Rc::new(WorkletThreadPool::spawn(init)) Rc::new(WorkletThreadPool::spawn(init))
}) })
@ -949,6 +954,7 @@ impl ScriptThread {
inherited_secure_context: state.inherited_secure_context, inherited_secure_context: state.inherited_secure_context,
layout_factory, layout_factory,
relative_mouse_down_point: Cell::new(Point2D::zero()), relative_mouse_down_point: Cell::new(Point2D::zero()),
protocols: Arc::new(state.protocols),
} }
} }
@ -3125,6 +3131,7 @@ impl ScriptThread {
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
self.gpu_id_hub.clone(), self.gpu_id_hub.clone(),
incomplete.load_data.inherited_secure_context, incomplete.load_data.inherited_secure_context,
self.protocols.clone(),
); );
let _realm = enter_realm(&*window); let _realm = enter_realm(&*window);

View file

@ -1032,6 +1032,8 @@ fn create_constellation(
let bluetooth_thread: IpcSender<BluetoothRequest> = let bluetooth_thread: IpcSender<BluetoothRequest> =
BluetoothThreadFactory::new(embedder_proxy.clone()); BluetoothThreadFactory::new(embedder_proxy.clone());
let protocols = Arc::new(protocols);
let (public_resource_threads, private_resource_threads) = new_resource_threads( let (public_resource_threads, private_resource_threads) = new_resource_threads(
devtools_sender.clone(), devtools_sender.clone(),
time_profiler_chan.clone(), time_profiler_chan.clone(),
@ -1040,7 +1042,7 @@ fn create_constellation(
config_dir, config_dir,
opts.certificate_path.clone(), opts.certificate_path.clone(),
opts.ignore_certificate_errors, opts.ignore_certificate_errors,
Arc::new(protocols), protocols.clone(),
); );
let system_font_service = Arc::new( let system_font_service = Arc::new(
@ -1075,6 +1077,7 @@ fn create_constellation(
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
wgpu_image_map, wgpu_image_map,
user_content_manager, user_content_manager,
protocols,
}; };
let layout_factory = Arc::new(LayoutFactoryImpl()); let layout_factory = Arc::new(LayoutFactoryImpl());

View file

@ -6,6 +6,7 @@
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::fmt; use std::fmt;
use std::sync::Arc;
use base::Epoch; use base::Epoch;
use base::id::{ use base::id::{
@ -23,7 +24,7 @@ use ipc_channel::Error as IpcError;
use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::ipc::{IpcReceiver, IpcSender};
use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBody}; use net_traits::request::{InsecureRequestsPolicy, Referrer, RequestBody};
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{CoreResourceMsg, ReferrerPolicy, ResourceThreads}; use net_traits::{CoreResourceMsg, Protocols, ReferrerPolicy, ResourceThreads};
use profile_traits::mem::MemoryReportResult; use profile_traits::mem::MemoryReportResult;
use profile_traits::{mem, time as profile_time}; use profile_traits::{mem, time as profile_time};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -433,6 +434,8 @@ pub struct WorkerGlobalScopeInit {
pub creation_url: Option<ServoUrl>, pub creation_url: Option<ServoUrl>,
/// True if secure context /// True if secure context
pub inherited_secure_context: Option<bool>, pub inherited_secure_context: Option<bool>,
/// Registered custom protocols
pub protocols: Arc<Protocols>,
} }
/// Common entities representing a network load origin /// Common entities representing a network load origin

View file

@ -1013,3 +1013,29 @@ pub fn set_default_accept_language(headers: &mut HeaderMap) {
pub static PRIVILEGED_SECRET: LazyLock<u32> = pub static PRIVILEGED_SECRET: LazyLock<u32> =
LazyLock::new(|| servo_rand::ServoRng::default().next_u32()); LazyLock::new(|| servo_rand::ServoRng::default().next_u32());
/// Registered custom protocols
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Protocols(HashMap<String, Protocol>);
impl Protocols {
/// Construct from a HashMap of string and protocols
pub fn new(protocols: HashMap<String, Protocol>) -> Self {
Self(protocols)
}
/// Test if the URL is potentially trustworthy or the custom protocol is registered as secure
pub fn is_url_potentially_trustworthy(&self, url: &ServoUrl) -> bool {
url.is_potentially_trustworthy() ||
self.0
.get(url.scheme())
.is_some_and(|protocol| protocol.is_secure)
}
}
/// A custom protocol
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Protocol {
/// If this custom protocol is considered secure context
pub is_secure: bool,
}

View file

@ -35,9 +35,9 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender};
use keyboard_types::Modifiers; use keyboard_types::Modifiers;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use media::WindowGLContext; use media::WindowGLContext;
use net_traits::ResourceThreads;
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{Protocols, ResourceThreads};
use pixels::PixelFormat; use pixels::PixelFormat;
use profile_traits::mem; use profile_traits::mem;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -324,6 +324,8 @@ pub struct InitialScriptState {
pub player_context: WindowGLContext, pub player_context: WindowGLContext,
/// User content manager /// User content manager
pub user_content_manager: UserContentManager, pub user_content_manager: UserContentManager,
/// Registered custom protocols
pub protocols: Protocols,
} }
/// Errors from executing a paint worklet /// Errors from executing a paint worklet