diff options
Diffstat (limited to 'components/net/protocols/mod.rs')
-rw-r--r-- | components/net/protocols/mod.rs | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/components/net/protocols/mod.rs b/components/net/protocols/mod.rs index f8b989b9623..6dc58ceab64 100644 --- a/components/net/protocols/mod.rs +++ b/components/net/protocols/mod.rs @@ -14,6 +14,7 @@ use log::error; use net_traits::filemanager_thread::RelativePos; use net_traits::request::Request; use net_traits::response::Response; +use servo_url::ServoUrl; use crate::fetch::methods::{DoneChannel, FetchContext, RangeRequestBounds}; @@ -47,6 +48,15 @@ pub trait ProtocolHandler: Send + Sync { fn is_fetchable(&self) -> bool { false } + + /// Specify if this custom protocol can be used in a [secure context] + /// + /// Note: this only works for bypassing mixed content checks right now + /// + /// [secure context]: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts + fn is_secure(&self) -> bool { + false + } } #[derive(Default)] @@ -54,27 +64,45 @@ pub struct ProtocolRegistry { pub(crate) handlers: HashMap<String, Box<dyn ProtocolHandler>>, // Maps scheme -> handler } +#[derive(Clone, Copy, Debug)] +pub enum ProtocolRegisterError { + ForbiddenScheme, + SchemeAlreadyRegistered, +} + impl ProtocolRegistry { pub fn with_internal_protocols() -> Self { let mut registry = Self::default(); - registry.register("data", DataProtocolHander::default()); - registry.register("blob", BlobProtocolHander::default()); - registry.register("file", FileProtocolHander::default()); + // We just created a new registry, and know that we aren't using + // any forbidden schemes, so this should never panic. + registry + .register("data", DataProtocolHander::default()) + .expect("Infallible"); + registry + .register("blob", BlobProtocolHander::default()) + .expect("Infallible"); + registry + .register("file", FileProtocolHander::default()) + .expect("Infallible"); registry } - pub fn register(&mut self, scheme: &str, handler: impl ProtocolHandler + 'static) -> bool { + pub fn register( + &mut self, + scheme: &str, + handler: impl ProtocolHandler + 'static, + ) -> Result<(), ProtocolRegisterError> { if FORBIDDEN_SCHEMES.contains(&scheme) { error!("Protocol handler for '{scheme}' is not allowed to be registered."); - return false; + return Err(ProtocolRegisterError::ForbiddenScheme); } if let Entry::Vacant(entry) = self.handlers.entry(scheme.into()) { entry.insert(Box::new(handler)); - true + Ok(()) } else { error!("Protocol handler for '{scheme}' is already registered."); - false + Err(ProtocolRegisterError::SchemeAlreadyRegistered) } } @@ -96,9 +124,22 @@ impl ProtocolRegistry { pub fn is_fetchable(&self, scheme: &str) -> bool { self.handlers .get(scheme) - .map(|handler| handler.is_fetchable()) - .unwrap_or(false) + .is_some_and(|handler| handler.is_fetchable()) } + + pub fn is_secure(&self, scheme: &str) -> bool { + self.handlers + .get(scheme) + .is_some_and(|handler| handler.is_secure()) + } +} + +/// Test if the URL is potentially trustworthy or the custom protocol is registered as secure +pub fn is_url_potentially_trustworthy( + protocol_registry: &ProtocolRegistry, + url: &ServoUrl, +) -> bool { + url.is_potentially_trustworthy() || protocol_registry.is_secure(url.scheme()) } pub fn range_not_satisfiable_error(response: &mut Response) { |