aboutsummaryrefslogtreecommitdiffstats
path: root/components/script_bindings/principals.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script_bindings/principals.rs')
-rw-r--r--components/script_bindings/principals.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/components/script_bindings/principals.rs b/components/script_bindings/principals.rs
new file mode 100644
index 00000000000..6b30f71fb7e
--- /dev/null
+++ b/components/script_bindings/principals.rs
@@ -0,0 +1,128 @@
+/* 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 std::marker::PhantomData;
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+use std::ptr::NonNull;
+
+use js::glue::{CreateRustJSPrincipals, GetRustJSPrincipalsPrivate};
+use js::jsapi::{JS_DropPrincipals, JS_HoldPrincipals, JSPrincipals};
+use js::rust::Runtime;
+use servo_url::MutableOrigin;
+
+use crate::DomTypes;
+use crate::interfaces::DomHelpers;
+
+/// An owned reference to Servo's `JSPrincipals` instance.
+#[repr(transparent)]
+pub struct ServoJSPrincipals(NonNull<JSPrincipals>);
+
+impl ServoJSPrincipals {
+ pub fn new<D: DomTypes>(origin: &MutableOrigin) -> Self {
+ unsafe {
+ let private: Box<MutableOrigin> = Box::new(origin.clone());
+ let raw = CreateRustJSPrincipals(
+ <D as DomHelpers<D>>::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.
+ ///
+ /// # Safety
+ /// `raw` must point to a valid JSPrincipals value.
+ #[inline]
+ pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
+ JS_HoldPrincipals(raw.as_ptr());
+ Self(raw)
+ }
+
+ #[inline]
+ pub fn origin(&self) -> MutableOrigin {
+ unsafe {
+ 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) {
+ if let Some(cx) = Runtime::get() {
+ unsafe { JS_DropPrincipals(cx.as_ptr(), 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
+ }
+}