script/dom/bindings/
principals.rs1use std::ptr::NonNull;
6
7use js::glue::{DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, JSPrincipalsCallbacks};
8use js::jsapi::{
9 JS_ReadUint32Pair, JSContext, JSPrincipals, JSStructuredCloneReader, JSStructuredCloneWriter,
10};
11use script_bindings::principals::{ServoJSPrincipals, ServoJSPrincipalsRef};
12use servo_url::MutableOrigin;
13
14use super::structuredclone::StructuredCloneTags;
15use crate::DomTypeHolder;
16
17#[expect(unused)]
18pub(crate) unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals) {
19 unsafe {
20 Box::from_raw(GetRustJSPrincipalsPrivate(principals) as *mut MutableOrigin);
21 DestroyRustJSPrincipals(principals);
22 }
23}
24
25pub(crate) unsafe extern "C" fn write_jsprincipal(
26 principal: *mut JSPrincipals,
27 _cx: *mut JSContext,
28 writer: *mut JSStructuredCloneWriter,
29) -> bool {
30 let Some(principal) = NonNull::new(principal) else {
31 return false;
32 };
33 let obj = unsafe { ServoJSPrincipalsRef::from_raw_nonnull(principal) };
34 let origin = obj.origin();
35 let Ok(bytes_of_origin) = postcard::to_stdvec(&origin) else {
36 return false;
37 };
38 let Ok(len) = bytes_of_origin.len().try_into() else {
39 return false;
40 };
41
42 unsafe {
43 if !js::jsapi::JS_WriteUint32PairUnchecked(
44 writer,
45 StructuredCloneTags::Principals as u32,
46 len,
47 ) {
48 return false;
49 }
50 if !js::jsapi::JS_WriteBytes(writer, bytes_of_origin.as_ptr() as _, len as usize) {
51 return false;
52 }
53 }
54
55 true
56}
57
58pub(crate) unsafe extern "C" fn read_jsprincipal(
59 _cx: *mut JSContext,
60 reader: *mut JSStructuredCloneReader,
61 principals: *mut *mut JSPrincipals,
62) -> bool {
63 let mut tag: u32 = 0;
64 let mut len: u32 = 0;
65
66 unsafe {
67 if !JS_ReadUint32Pair(reader, &mut tag as *mut u32, &mut len as *mut u32) {
68 return false;
69 }
70 }
71
72 if tag != StructuredCloneTags::Principals as u32 {
73 return false;
74 }
75 let mut bytes = vec![0u8; len as usize];
76
77 unsafe {
78 if !js::jsapi::JS_ReadBytes(reader, bytes.as_mut_ptr() as _, len as usize) {
79 return false;
80 }
81 }
82
83 let Ok(origin) = postcard::from_bytes(&bytes[..]) else {
84 return false;
85 };
86 let principal = ServoJSPrincipals::new::<DomTypeHolder>(&origin);
87 unsafe { *principals = principal.as_raw() };
88 std::mem::forget(principal);
90 true
91}
92
93pub(crate) const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks {
94 write: Some(write_jsprincipal),
95 isSystemPrincipal: Some(principals_is_system_principal),
96 isAddonPrincipal: Some(principals_is_addon_principal),
97};
98
99unsafe extern "C" fn principals_is_system_principal(_: *mut JSPrincipals) -> bool {
100 false
101}
102
103unsafe extern "C" fn principals_is_addon_principal(_: *mut JSPrincipals) -> bool {
104 false
105}
106
107pub(crate) unsafe extern "C" fn subsumes(obj: *mut JSPrincipals, other: *mut JSPrincipals) -> bool {
109 match (NonNull::new(obj), NonNull::new(other)) {
110 (Some(obj), Some(other)) => {
111 let obj = unsafe { ServoJSPrincipalsRef::from_raw_nonnull(obj) };
112 let other = unsafe { ServoJSPrincipalsRef::from_raw_nonnull(other) };
113 let obj_origin = obj.origin();
114 let other_origin = other.origin();
115 obj_origin.same_origin_domain(&other_origin)
116 },
117 (None, Some(_)) => {
118 true
121 },
122 _ => {
123 warn!("Received null JSPrincipal argument.");
124 false
125 },
126 }
127}