diff options
Diffstat (limited to 'components/script/dom/bindings/principals.rs')
-rw-r--r-- | components/script/dom/bindings/principals.rs | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/components/script/dom/bindings/principals.rs b/components/script/dom/bindings/principals.rs new file mode 100644 index 00000000000..b16bc8859db --- /dev/null +++ b/components/script/dom/bindings/principals.rs @@ -0,0 +1,139 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use js::{ + glue::{ + CreateRustJSPrincipals, DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, + JSPrincipalsCallbacks, + }, + jsapi::{JSPrincipals, JS_DropPrincipals, JS_HoldPrincipals}, + rust::Runtime, +}; +use servo_url::MutableOrigin; +use std::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull}; + +/// An owned reference to Servo's `JSPrincipals` instance. +#[repr(transparent)] +pub struct ServoJSPrincipals(NonNull<JSPrincipals>); + +impl ServoJSPrincipals { + pub fn new(origin: &MutableOrigin) -> Self { + unsafe { + let private: Box<MutableOrigin> = Box::new(origin.clone()); + let raw = CreateRustJSPrincipals(&PRINCIPALS_CALLBACKS, Box::into_raw(private) as _); + // The created `JSPrincipals` object has an initial reference + // count of zero, so the following code will set it to one + Self::from_raw_nonnull(NonNull::new_unchecked(raw)) + } + } + + /// Construct `Self` from a raw `*mut JSPrincipals`, incrementing its + /// reference count. + #[inline] + pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self { + JS_HoldPrincipals(raw.as_ptr()); + Self(raw) + } + + #[inline] + pub unsafe fn origin(&self) -> MutableOrigin { + let origin = GetRustJSPrincipalsPrivate(self.0.as_ptr()) as *mut MutableOrigin; + (*origin).clone() + } + + #[inline] + pub fn as_raw_nonnull(&self) -> NonNull<JSPrincipals> { + self.0 + } + + #[inline] + pub fn as_raw(&self) -> *mut JSPrincipals { + self.0.as_ptr() + } +} + +impl Clone for ServoJSPrincipals { + #[inline] + fn clone(&self) -> Self { + unsafe { Self::from_raw_nonnull(self.as_raw_nonnull()) } + } +} + +impl Drop for ServoJSPrincipals { + #[inline] + fn drop(&mut self) { + unsafe { JS_DropPrincipals(Runtime::get(), self.as_raw()) }; + } +} + +/// A borrowed reference to Servo's `JSPrincipals` instance. Does not update the +/// reference count on creation and deletion. +pub struct ServoJSPrincipalsRef<'a>(ManuallyDrop<ServoJSPrincipals>, PhantomData<&'a ()>); + +impl ServoJSPrincipalsRef<'_> { + /// Construct `Self` from a raw `NonNull<JSPrincipals>`. + /// + /// # Safety + /// + /// `ServoJSPrincipalsRef` does not update the reference count of the + /// wrapped `JSPrincipals` object. It's up to the caller to ensure the + /// returned `ServoJSPrincipalsRef` object or any clones are not used past + /// the lifetime of the wrapped object. + #[inline] + pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self { + // Don't use `ServoJSPrincipals::from_raw_nonnull`; we don't want to + // update the reference count + Self(ManuallyDrop::new(ServoJSPrincipals(raw)), PhantomData) + } + + /// Construct `Self` from a raw `*mut JSPrincipals`. + /// + /// # Safety + /// + /// The behavior is undefined if `raw` is null. See also + /// [`Self::from_raw_nonnull`]. + #[inline] + pub unsafe fn from_raw_unchecked(raw: *mut JSPrincipals) -> Self { + Self::from_raw_nonnull(NonNull::new_unchecked(raw)) + } +} + +impl Clone for ServoJSPrincipalsRef<'_> { + #[inline] + fn clone(&self) -> Self { + Self(ManuallyDrop::new(ServoJSPrincipals(self.0 .0)), PhantomData) + } +} + +impl Deref for ServoJSPrincipalsRef<'_> { + type Target = ServoJSPrincipals; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals) { + Box::from_raw(GetRustJSPrincipalsPrivate(principals) as *mut MutableOrigin); + DestroyRustJSPrincipals(principals); +} + +const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks { + write: None, + isSystemOrAddonPrincipal: Some(principals_is_system_or_addon_principal), +}; + +unsafe extern "C" fn principals_is_system_or_addon_principal(_: *mut JSPrincipals) -> bool { + false +} + +//TODO is same_origin_domain equivalent to subsumes for our purposes +pub unsafe extern "C" fn subsumes(obj: *mut JSPrincipals, other: *mut JSPrincipals) -> bool { + let obj = ServoJSPrincipalsRef::from_raw_unchecked(obj); + let other = ServoJSPrincipalsRef::from_raw_unchecked(other); + let obj_origin = obj.origin(); + let other_origin = other.origin(); + obj_origin.same_origin_domain(&other_origin) +} |