1use dom_struct::dom_struct;
6use js::rust::HandleValue;
7use script_bindings::callback::TracedCallback;
8use script_bindings::reflector::{DomObject, Reflector, reflect_dom_object};
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;
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::bindings::str::DOMString;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
24use crate::dom::trustedtypes::trustedscript::TrustedScript;
25use crate::dom::trustedtypes::trustedscripturl::TrustedScriptURL;
26
27#[dom_struct]
28#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
29pub struct TrustedTypePolicy {
30 reflector_: Reflector,
31
32 name: String,
33
34 create_html: Option<TracedCallback<CreateHTMLCallback>>,
35 create_script: Option<TracedCallback<CreateScriptCallback>>,
36 create_script_url: Option<TracedCallback<CreateScriptURLCallback>>,
37}
38
39#[derive(AsRefStr, Clone)]
40pub(crate) enum TrustedType {
41 TrustedHTML,
42 TrustedScript,
43 TrustedScriptURL,
44}
45
46impl TrustedType {
47 pub(crate) fn matches_idl_trusted_type(&self, idl_trusted_type: &TrustedTypeOrString) -> bool {
48 match self {
49 TrustedType::TrustedHTML => {
50 matches!(idl_trusted_type, TrustedTypeOrString::TrustedHTML(_))
51 },
52 TrustedType::TrustedScript => {
53 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScript(_))
54 },
55 TrustedType::TrustedScriptURL => {
56 matches!(idl_trusted_type, TrustedTypeOrString::TrustedScriptURL(_))
57 },
58 }
59 }
60}
61
62impl TrustedTypePolicy {
63 fn new_inherited(name: String, options: &TrustedTypePolicyOptions) -> Self {
64 Self {
65 reflector_: Reflector::new(),
66 name,
67 create_html: options.createHTML.clone(),
68 create_script: options.createScript.clone(),
69 create_script_url: options.createScriptURL.clone(),
70 }
71 }
72
73 pub(crate) fn new(
74 cx: &mut js::context::JSContext,
75 name: String,
76 options: &TrustedTypePolicyOptions,
77 global: &GlobalScope,
78 ) -> DomRoot<Self> {
79 reflect_dom_object(cx, Box::new(Self::new_inherited(name, options)), global)
80 }
81
82 fn check_callback_if_missing(throw_if_missing: bool) -> Fallible<Option<DOMString>> {
84 if throw_if_missing {
86 Err(Type(c"Cannot find type".to_owned()))
87 } else {
88 Ok(None)
90 }
91 }
92
93 pub(crate) fn get_trusted_type_policy_value(
95 &self,
96 cx: &mut js::context::JSContext,
97 expected_type: TrustedType,
98 input: DOMString,
99 arguments: Vec<HandleValue>,
100 throw_if_missing: bool,
101 ) -> Fallible<Option<DOMString>> {
102 match expected_type {
104 TrustedType::TrustedHTML => match &self.create_html {
105 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
107 Some(callback) => {
109 callback.Call__(cx, input, arguments, ExceptionHandling::Rethrow)
113 },
114 },
115 TrustedType::TrustedScript => match &self.create_script {
116 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
118 Some(callback) => {
120 callback.Call__(cx, input, arguments, ExceptionHandling::Rethrow)
124 },
125 },
126 TrustedType::TrustedScriptURL => match &self.create_script_url {
127 None => TrustedTypePolicy::check_callback_if_missing(throw_if_missing),
129 Some(callback) => {
131 callback
135 .Call__(cx, input, arguments, ExceptionHandling::Rethrow)
136 .map(|result| result.map(DOMString::from))
137 },
138 },
139 }
140 }
141
142 fn create_trusted_type<R, TrustedTypeCallback>(
154 &self,
155 cx: &mut js::context::JSContext,
156 expected_type: TrustedType,
157 input: DOMString,
158 arguments: Vec<HandleValue>,
159 trusted_type_creation_callback: TrustedTypeCallback,
160 ) -> Fallible<DomRoot<R>>
161 where
162 R: DomObject,
163 TrustedTypeCallback: FnOnce(&mut js::context::JSContext, DOMString) -> DomRoot<R>,
164 {
165 let policy_value =
168 self.get_trusted_type_policy_value(cx, expected_type, input, arguments, true);
169 match policy_value {
170 Err(error) => Err(error),
172 Ok(policy_value) => {
173 let data_string = match policy_value {
175 Some(value) => value,
176 None => DOMString::new(),
178 };
179 Ok(trusted_type_creation_callback(cx, data_string))
182 },
183 }
184 }
185}
186
187impl TrustedTypePolicyMethods<crate::DomTypeHolder> for TrustedTypePolicy {
188 fn Name(&self) -> DOMString {
190 DOMString::from(&*self.name)
191 }
192 fn CreateHTML(
194 &self,
195 cx: &mut js::context::JSContext,
196 input: DOMString,
197 arguments: Vec<HandleValue>,
198 ) -> Fallible<DomRoot<TrustedHTML>> {
199 self.create_trusted_type(
200 cx,
201 TrustedType::TrustedHTML,
202 input,
203 arguments,
204 |cx, data_string| TrustedHTML::new(cx, data_string, &self.global()),
205 )
206 }
207 fn CreateScript(
209 &self,
210 cx: &mut js::context::JSContext,
211 input: DOMString,
212 arguments: Vec<HandleValue>,
213 ) -> Fallible<DomRoot<TrustedScript>> {
214 self.create_trusted_type(
215 cx,
216 TrustedType::TrustedScript,
217 input,
218 arguments,
219 |cx, data_string| TrustedScript::new(cx, data_string, &self.global()),
220 )
221 }
222 fn CreateScriptURL(
224 &self,
225 cx: &mut js::context::JSContext,
226 input: DOMString,
227 arguments: Vec<HandleValue>,
228 ) -> Fallible<DomRoot<TrustedScriptURL>> {
229 self.create_trusted_type(
230 cx,
231 TrustedType::TrustedScriptURL,
232 input,
233 arguments,
234 |cx, data_string| TrustedScriptURL::new(cx, data_string, &self.global()),
235 )
236 }
237}