1use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use js::rust::HandleValue;
9use strum::AsRefStr;
10
11use crate::dom::bindings::callback::ExceptionHandling;
12use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyBinding::TrustedTypePolicyMethods;
13use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyFactoryBinding::{
14 CreateHTMLCallback, CreateScriptCallback, CreateScriptURLCallback, TrustedTypePolicyOptions,
15};
16use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString as TrustedTypeOrString;
17use crate::dom::bindings::error::Error::Type;
18use crate::dom::bindings::error::Fallible;
19use crate::dom::bindings::reflector::{
20 DomGlobal, DomObject, Reflector, reflect_dom_object_with_cx,
21};
22use crate::dom::bindings::root::DomRoot;
23use crate::dom::bindings::str::DOMString;
24use crate::dom::globalscope::GlobalScope;
25use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
26use crate::dom::trustedtypes::trustedscript::TrustedScript;
27use crate::dom::trustedtypes::trustedscripturl::TrustedScriptURL;
28use crate::script_runtime::CanGc;
29
30#[dom_struct]
31pub struct TrustedTypePolicy {
32 reflector_: Reflector,
33
34 name: String,
35
36 #[conditional_malloc_size_of]
37 create_html: Option<Rc<CreateHTMLCallback>>,
38 #[conditional_malloc_size_of]
39 create_script: Option<Rc<CreateScriptCallback>>,
40 #[conditional_malloc_size_of]
41 create_script_url: Option<Rc<CreateScriptURLCallback>>,
42}
43
44#[derive(AsRefStr, Clone)]
45pub(crate) enum TrustedType {
46 TrustedHTML,
47 TrustedScript,
48 TrustedScriptURL,
49}
50
51impl TrustedType {
52 pub(crate) fn matches_idl_trusted_type(&self, idl_trusted_type: &TrustedTypeOrString) -> bool {
53 match self {
54 TrustedType::TrustedHTML => {
55 matches!(idl_trusted_type, TrustedTypeOrString::TrustedHTML(_))
56 },
57 TrustedType::TrustedScript => {
58 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScript(_))
59 },
60 TrustedType::TrustedScriptURL => {
61 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScriptURL(_))
62 },
63 }
64 }
65}
66
67impl TrustedTypePolicy {
68 fn new_inherited(name: String, options: &TrustedTypePolicyOptions) -> Self {
69 Self {
70 reflector_: Reflector::new(),
71 name,
72 create_html: options.createHTML.clone(),
73 create_script: options.createScript.clone(),
74 create_script_url: options.createScriptURL.clone(),
75 }
76 }
77
78 pub(crate) fn new(
79 cx: &mut js::context::JSContext,
80 name: String,
81 options: &TrustedTypePolicyOptions,
82 global: &GlobalScope,
83 ) -> DomRoot<Self> {
84 reflect_dom_object_with_cx(Box::new(Self::new_inherited(name, options)), global, cx)
85 }
86
87 fn check_callback_if_missing(throw_if_missing: bool) -> Fallible<Option<DOMString>> {
89 if throw_if_missing {
91 Err(Type(c"Cannot find type".to_owned()))
92 } else {
93 Ok(None)
95 }
96 }
97
98 pub(crate) fn get_trusted_type_policy_value(
100 &self,
101 cx: &mut js::context::JSContext,
102 expected_type: TrustedType,
103 input: DOMString,
104 arguments: Vec<HandleValue>,
105 throw_if_missing: bool,
106 ) -> Fallible<Option<DOMString>> {
107 match expected_type {
109 TrustedType::TrustedHTML => match &self.create_html {
110 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
112 Some(callback) => {
114 callback.Call__(
118 input,
119 arguments,
120 ExceptionHandling::Rethrow,
121 CanGc::from_cx(cx),
122 )
123 },
124 },
125 TrustedType::TrustedScript => match &self.create_script {
126 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
128 Some(callback) => {
130 callback.Call__(
134 input,
135 arguments,
136 ExceptionHandling::Rethrow,
137 CanGc::from_cx(cx),
138 )
139 },
140 },
141 TrustedType::TrustedScriptURL => match &self.create_script_url {
142 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
144 Some(callback) => {
146 callback
150 .Call__(
151 input,
152 arguments,
153 ExceptionHandling::Rethrow,
154 CanGc::from_cx(cx),
155 )
156 .map(|result| result.map(DOMString::from))
157 },
158 },
159 }
160 }
161
162 fn create_trusted_type<R, TrustedTypeCallback>(
174 &self,
175 cx: &mut js::context::JSContext,
176 expected_type: TrustedType,
177 input: DOMString,
178 arguments: Vec<HandleValue>,
179 trusted_type_creation_callback: TrustedTypeCallback,
180 ) -> Fallible<DomRoot<R>>
181 where
182 R: DomObject,
183 TrustedTypeCallback: FnOnce(&mut js::context::JSContext, DOMString) -> DomRoot<R>,
184 {
185 let policy_value =
188 self.get_trusted_type_policy_value(cx, expected_type, input, arguments, true);
189 match policy_value {
190 Err(error) => Err(error),
192 Ok(policy_value) => {
193 let data_string = match policy_value {
195 Some(value) => value,
196 None => DOMString::new(),
198 };
199 Ok(trusted_type_creation_callback(cx, data_string))
202 },
203 }
204 }
205}
206
207impl TrustedTypePolicyMethods<crate::DomTypeHolder> for TrustedTypePolicy {
208 fn Name(&self) -> DOMString {
210 DOMString::from(&*self.name)
211 }
212 fn CreateHTML(
214 &self,
215 cx: &mut js::context::JSContext,
216 input: DOMString,
217 arguments: Vec<HandleValue>,
218 ) -> Fallible<DomRoot<TrustedHTML>> {
219 self.create_trusted_type(
220 cx,
221 TrustedType::TrustedHTML,
222 input,
223 arguments,
224 |cx, data_string| TrustedHTML::new(cx, data_string, &self.global()),
225 )
226 }
227 fn CreateScript(
229 &self,
230 cx: &mut js::context::JSContext,
231 input: DOMString,
232 arguments: Vec<HandleValue>,
233 ) -> Fallible<DomRoot<TrustedScript>> {
234 self.create_trusted_type(
235 cx,
236 TrustedType::TrustedScript,
237 input,
238 arguments,
239 |cx, data_string| TrustedScript::new(cx, data_string, &self.global()),
240 )
241 }
242 fn CreateScriptURL(
244 &self,
245 cx: &mut js::context::JSContext,
246 input: DOMString,
247 arguments: Vec<HandleValue>,
248 ) -> Fallible<DomRoot<TrustedScriptURL>> {
249 self.create_trusted_type(
250 cx,
251 TrustedType::TrustedScriptURL,
252 input,
253 arguments,
254 |cx, data_string| TrustedScriptURL::new(cx, data_string, &self.global()),
255 )
256 }
257}