1use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use js::rust::HandleValue;
9use script_bindings::reflector::{DomObject, Reflector, reflect_dom_object_with_cx};
10use strum::AsRefStr;
11
12use crate::dom::bindings::callback::ExceptionHandling;
13use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyBinding::TrustedTypePolicyMethods;
14use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyFactoryBinding::{
15 CreateHTMLCallback, CreateScriptCallback, CreateScriptURLCallback, TrustedTypePolicyOptions,
16};
17use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString as TrustedTypeOrString;
18use crate::dom::bindings::error::Error::Type;
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::reflector::DomGlobal;
21use crate::dom::bindings::root::DomRoot;
22use crate::dom::bindings::str::DOMString;
23use crate::dom::globalscope::GlobalScope;
24use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
25use crate::dom::trustedtypes::trustedscript::TrustedScript;
26use crate::dom::trustedtypes::trustedscripturl::TrustedScriptURL;
27
28#[dom_struct]
29pub struct TrustedTypePolicy {
30 reflector_: Reflector,
31
32 name: String,
33
34 #[conditional_malloc_size_of]
35 create_html: Option<Rc<CreateHTMLCallback>>,
36 #[conditional_malloc_size_of]
37 create_script: Option<Rc<CreateScriptCallback>>,
38 #[conditional_malloc_size_of]
39 create_script_url: Option<Rc<CreateScriptURLCallback>>,
40}
41
42#[derive(AsRefStr, Clone)]
43pub(crate) enum TrustedType {
44 TrustedHTML,
45 TrustedScript,
46 TrustedScriptURL,
47}
48
49impl TrustedType {
50 pub(crate) fn matches_idl_trusted_type(&self, idl_trusted_type: &TrustedTypeOrString) -> bool {
51 match self {
52 TrustedType::TrustedHTML => {
53 matches!(idl_trusted_type, TrustedTypeOrString::TrustedHTML(_))
54 },
55 TrustedType::TrustedScript => {
56 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScript(_))
57 },
58 TrustedType::TrustedScriptURL => {
59 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScriptURL(_))
60 },
61 }
62 }
63}
64
65impl TrustedTypePolicy {
66 fn new_inherited(name: String, options: &TrustedTypePolicyOptions) -> Self {
67 Self {
68 reflector_: Reflector::new(),
69 name,
70 create_html: options.createHTML.clone(),
71 create_script: options.createScript.clone(),
72 create_script_url: options.createScriptURL.clone(),
73 }
74 }
75
76 pub(crate) fn new(
77 cx: &mut js::context::JSContext,
78 name: String,
79 options: &TrustedTypePolicyOptions,
80 global: &GlobalScope,
81 ) -> DomRoot<Self> {
82 reflect_dom_object_with_cx(Box::new(Self::new_inherited(name, options)), global, cx)
83 }
84
85 fn check_callback_if_missing(throw_if_missing: bool) -> Fallible<Option<DOMString>> {
87 if throw_if_missing {
89 Err(Type(c"Cannot find type".to_owned()))
90 } else {
91 Ok(None)
93 }
94 }
95
96 pub(crate) fn get_trusted_type_policy_value(
98 &self,
99 cx: &mut js::context::JSContext,
100 expected_type: TrustedType,
101 input: DOMString,
102 arguments: Vec<HandleValue>,
103 throw_if_missing: bool,
104 ) -> Fallible<Option<DOMString>> {
105 match expected_type {
107 TrustedType::TrustedHTML => match &self.create_html {
108 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
110 Some(callback) => {
112 callback.Call__(cx, input, arguments, ExceptionHandling::Rethrow)
116 },
117 },
118 TrustedType::TrustedScript => match &self.create_script {
119 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
121 Some(callback) => {
123 callback.Call__(cx, input, arguments, ExceptionHandling::Rethrow)
127 },
128 },
129 TrustedType::TrustedScriptURL => match &self.create_script_url {
130 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
132 Some(callback) => {
134 callback
138 .Call__(cx, input, arguments, ExceptionHandling::Rethrow)
139 .map(|result| result.map(DOMString::from))
140 },
141 },
142 }
143 }
144
145 fn create_trusted_type<R, TrustedTypeCallback>(
157 &self,
158 cx: &mut js::context::JSContext,
159 expected_type: TrustedType,
160 input: DOMString,
161 arguments: Vec<HandleValue>,
162 trusted_type_creation_callback: TrustedTypeCallback,
163 ) -> Fallible<DomRoot<R>>
164 where
165 R: DomObject,
166 TrustedTypeCallback: FnOnce(&mut js::context::JSContext, DOMString) -> DomRoot<R>,
167 {
168 let policy_value =
171 self.get_trusted_type_policy_value(cx, expected_type, input, arguments, true);
172 match policy_value {
173 Err(error) => Err(error),
175 Ok(policy_value) => {
176 let data_string = match policy_value {
178 Some(value) => value,
179 None => DOMString::new(),
181 };
182 Ok(trusted_type_creation_callback(cx, data_string))
185 },
186 }
187 }
188}
189
190impl TrustedTypePolicyMethods<crate::DomTypeHolder> for TrustedTypePolicy {
191 fn Name(&self) -> DOMString {
193 DOMString::from(&*self.name)
194 }
195 fn CreateHTML(
197 &self,
198 cx: &mut js::context::JSContext,
199 input: DOMString,
200 arguments: Vec<HandleValue>,
201 ) -> Fallible<DomRoot<TrustedHTML>> {
202 self.create_trusted_type(
203 cx,
204 TrustedType::TrustedHTML,
205 input,
206 arguments,
207 |cx, data_string| TrustedHTML::new(cx, data_string, &self.global()),
208 )
209 }
210 fn CreateScript(
212 &self,
213 cx: &mut js::context::JSContext,
214 input: DOMString,
215 arguments: Vec<HandleValue>,
216 ) -> Fallible<DomRoot<TrustedScript>> {
217 self.create_trusted_type(
218 cx,
219 TrustedType::TrustedScript,
220 input,
221 arguments,
222 |cx, data_string| TrustedScript::new(cx, data_string, &self.global()),
223 )
224 }
225 fn CreateScriptURL(
227 &self,
228 cx: &mut js::context::JSContext,
229 input: DOMString,
230 arguments: Vec<HandleValue>,
231 ) -> Fallible<DomRoot<TrustedScriptURL>> {
232 self.create_trusted_type(
233 cx,
234 TrustedType::TrustedScriptURL,
235 input,
236 arguments,
237 |cx, data_string| TrustedScriptURL::new(cx, data_string, &self.global()),
238 )
239 }
240}