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::{DomGlobal, DomObject, Reflector, reflect_dom_object};
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::bindings::str::DOMString;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::trustedhtml::TrustedHTML;
24use crate::dom::trustedscript::TrustedScript;
25use crate::dom::trustedscripturl::TrustedScriptURL;
26use crate::script_runtime::{CanGc, JSContext};
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 name: String,
78 options: &TrustedTypePolicyOptions,
79 global: &GlobalScope,
80 can_gc: CanGc,
81 ) -> DomRoot<Self> {
82 reflect_dom_object(Box::new(Self::new_inherited(name, options)), global, can_gc)
83 }
84
85 fn check_callback_if_missing(throw_if_missing: bool) -> Fallible<Option<DOMString>> {
87 if throw_if_missing {
89 Err(Type("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 expected_type: TrustedType,
100 input: DOMString,
101 arguments: Vec<HandleValue>,
102 throw_if_missing: bool,
103 can_gc: CanGc,
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__(input, arguments, ExceptionHandling::Rethrow, can_gc)
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__(input, arguments, ExceptionHandling::Rethrow, can_gc)
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__(input, arguments, ExceptionHandling::Rethrow, can_gc)
139 .map(|result| result.map(DOMString::from))
140 },
141 },
142 }
143 }
144
145 fn create_trusted_type<R, TrustedTypeCallback>(
157 &self,
158 expected_type: TrustedType,
159 input: DOMString,
160 arguments: Vec<HandleValue>,
161 trusted_type_creation_callback: TrustedTypeCallback,
162 can_gc: CanGc,
163 ) -> Fallible<DomRoot<R>>
164 where
165 R: DomObject,
166 TrustedTypeCallback: FnOnce(DOMString) -> DomRoot<R>,
167 {
168 let policy_value =
171 self.get_trusted_type_policy_value(expected_type, input, arguments, true, can_gc);
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(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: JSContext,
199 input: DOMString,
200 arguments: Vec<HandleValue>,
201 can_gc: CanGc,
202 ) -> Fallible<DomRoot<TrustedHTML>> {
203 self.create_trusted_type(
204 TrustedType::TrustedHTML,
205 input,
206 arguments,
207 |data_string| TrustedHTML::new(data_string, &self.global(), can_gc),
208 can_gc,
209 )
210 }
211 fn CreateScript(
213 &self,
214 _cx: JSContext,
215 input: DOMString,
216 arguments: Vec<HandleValue>,
217 can_gc: CanGc,
218 ) -> Fallible<DomRoot<TrustedScript>> {
219 self.create_trusted_type(
220 TrustedType::TrustedScript,
221 input,
222 arguments,
223 |data_string| TrustedScript::new(data_string, &self.global(), can_gc),
224 can_gc,
225 )
226 }
227 fn CreateScriptURL(
229 &self,
230 _cx: JSContext,
231 input: DOMString,
232 arguments: Vec<HandleValue>,
233 can_gc: CanGc,
234 ) -> Fallible<DomRoot<TrustedScriptURL>> {
235 self.create_trusted_type(
236 TrustedType::TrustedScriptURL,
237 input,
238 arguments,
239 |data_string| TrustedScriptURL::new(data_string, &self.global(), can_gc),
240 can_gc,
241 )
242 }
243}