use std::fmt;
use dom_struct::dom_struct;
use js::context::JSContext;
use js::jsapi::CompilationType;
use js::rust::HandleValue;
use crate::dom::bindings::codegen::Bindings::TrustedScriptBinding::TrustedScriptMethods;
use crate::dom::bindings::codegen::UnionTypes::TrustedScriptOrString;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_cx};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::csp::CspReporting;
use crate::dom::globalscope::GlobalScope;
use crate::dom::trustedtypes::trustedtypepolicy::TrustedType;
use crate::dom::trustedtypes::trustedtypepolicyfactory::{
DEFAULT_SCRIPT_SINK_GROUP, TrustedTypePolicyFactory,
};
#[dom_struct]
pub struct TrustedScript {
reflector_: Reflector,
data: DOMString,
}
impl TrustedScript {
fn new_inherited(data: DOMString) -> Self {
Self {
reflector_: Reflector::new(),
data,
}
}
pub(crate) fn new(cx: &mut JSContext, data: DOMString, global: &GlobalScope) -> DomRoot<Self> {
reflect_dom_object_with_cx(Box::new(Self::new_inherited(data)), global, cx)
}
pub(crate) fn get_trusted_type_compliant_string(
cx: &mut JSContext,
global: &GlobalScope,
value: TrustedScriptOrString,
sink: &str,
) -> Fallible<DOMString> {
match value {
TrustedScriptOrString::String(value) => {
TrustedTypePolicyFactory::get_trusted_type_compliant_string(
cx,
TrustedType::TrustedScript,
global,
value,
sink,
DEFAULT_SCRIPT_SINK_GROUP,
)
},
TrustedScriptOrString::TrustedScript(trusted_script) => Ok(trusted_script.data.clone()),
}
}
pub(crate) fn data(&self) -> &DOMString {
&self.data
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn can_compile_string_with_trusted_type(
cx: &mut JSContext,
global: &GlobalScope,
code_string: DOMString,
compilation_type: CompilationType,
parameter_strings: Vec<DOMString>,
body_string: DOMString,
parameter_args: Vec<TrustedScriptOrString>,
body_arg: HandleValue,
) -> bool {
let compilation_sink = if compilation_type == CompilationType::Function {
"Function"
} else {
"eval"
};
let mut is_trusted = match TrustedTypePolicyFactory::is_trusted_script(cx.into(), body_arg)
{
Ok(trusted_script) => {
body_string == trusted_script.data
},
_ => false,
};
if is_trusted {
assert!(parameter_args.len() == parameter_strings.len());
for index in 0..parameter_args.len() {
match ¶meter_args[index] {
TrustedScriptOrString::TrustedScript(trusted_script) => {
if parameter_strings[index] != *trusted_script.data() {
is_trusted = false;
}
},
TrustedScriptOrString::String(_) => {
is_trusted = false;
},
}
}
}
let source_string = if is_trusted {
code_string
} else {
match TrustedScript::get_trusted_type_compliant_string(
cx,
global,
TrustedScriptOrString::String(code_string.clone()),
compilation_sink,
) {
Err(_) => {
return false;
},
Ok(source_string) => {
if source_string != code_string {
return false;
}
source_string
},
}
};
global
.get_csp_list()
.is_js_evaluation_allowed(global, &source_string.str())
}
}
impl fmt::Display for TrustedScript {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.data.str())
}
}
impl TrustedScriptMethods<crate::DomTypeHolder> for TrustedScript {
fn Stringifier(&self) -> DOMString {
self.data.clone()
}
fn ToJSON(&self) -> DOMString {
self.data.clone()
}
}