Files
servo/components/script/dom/trustedscript.rs
Martin Robinson 8743a11ba4 tidy: Add a rule ensuring that // comments are followed by a space in Rust (#38698)
This shows up sometimes in code reviews, so it makes sense that tidy
enforces it. `rustfmt` supports this via comment normalization, but it
does many other things and is still an unstable feature (with bugs).

Testing: There are new tidy tests for this change.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-18 12:09:09 +00:00

160 lines
6.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::fmt;
use dom_struct::dom_struct;
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};
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::trustedtypepolicy::TrustedType;
use crate::dom::trustedtypepolicyfactory::{DEFAULT_SCRIPT_SINK_GROUP, TrustedTypePolicyFactory};
use crate::script_runtime::{CanGc, JSContext};
#[dom_struct]
pub struct TrustedScript {
reflector_: Reflector,
data: DOMString,
}
impl TrustedScript {
fn new_inherited(data: DOMString) -> Self {
Self {
reflector_: Reflector::new(),
data,
}
}
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new(data: DOMString, global: &GlobalScope, can_gc: CanGc) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited(data)), global, can_gc)
}
pub(crate) fn get_trusted_script_compliant_string(
global: &GlobalScope,
value: TrustedScriptOrString,
sink: &str,
can_gc: CanGc,
) -> Fallible<DOMString> {
match value {
TrustedScriptOrString::String(value) => {
TrustedTypePolicyFactory::get_trusted_type_compliant_string(
TrustedType::TrustedScript,
global,
value,
sink,
DEFAULT_SCRIPT_SINK_GROUP,
can_gc,
)
},
TrustedScriptOrString::TrustedScript(trusted_script) => Ok(trusted_script.data.clone()),
}
}
pub(crate) fn data(&self) -> DOMString {
self.data.clone()
}
/// <https://www.w3.org/TR/CSP/#can-compile-strings>
#[allow(clippy::too_many_arguments)]
pub(crate) fn can_compile_string_with_trusted_type(
cx: JSContext,
global: &GlobalScope,
code_string: DOMString,
compilation_type: CompilationType,
_parameter_strings: u8, // FIXME in bindings generation
body_string: DOMString,
_parameter_args: u8, // FIXME in bindings generation
body_arg: HandleValue,
can_gc: CanGc,
) -> bool {
// Step 2.1. Let compilationSink be "Function" if compilationType is "FUNCTION",
// and "eval" otherwise.
let compilation_sink = if compilation_type == CompilationType::Function {
"Function"
} else {
"eval"
};
// Step 2.2. Let isTrusted be true if bodyArg implements TrustedScript,
// and false otherwise.
let is_trusted = match TrustedTypePolicyFactory::is_trusted_script(cx, body_arg) {
// Step 2.3. If isTrusted is true then:
Ok(trusted_script) => {
// Step 2.3.1. If bodyString is not equal to bodyArgs data, set isTrusted to false.
body_string == trusted_script.data
},
_ => false,
};
// Step 2.4. If isTrusted is true, then:
// Step 2.4.1. Assert: parameterArgs [list/size=] is equal to [parameterStrings]' size.
// Step 2.4.2. For each index of the range 0 to |parameterArgs]' [list/size=]:
// Step 2.4.2.1. Let arg be parameterArgs[index].
// Step 2.4.2.2. If arg implements TrustedScript, then:
// Step 2.4.2.2.1. if parameterStrings[index] is not equal to args data,
// set isTrusted to false.
// Step 2.4.2.3. Otherwise, set isTrusted to false.
// Step 2.5. Let sourceToValidate be a new TrustedScript object created in realm
// whose data is set to codeString if isTrusted is true, and codeString otherwise.
let source_string = if is_trusted {
// We don't need to call the compliant string algorithm, as it would immediately
// unroll the type as allowed by copying the data. This allows us to skip creating
// the DOM object.
code_string
} else {
// Step 2.6. Let sourceString be the result of executing the
// Get Trusted Type compliant string algorithm, with TrustedScript, realm,
// sourceToValidate, compilationSink, and 'script'.
match TrustedScript::get_trusted_script_compliant_string(
global,
TrustedScriptOrString::String(code_string.clone()),
compilation_sink,
can_gc,
) {
// Step 2.7. If the algorithm throws an error, throw an EvalError.
Err(_) => {
return false;
},
Ok(source_string) => {
// Step 2.8. If sourceString is not equal to codeString, throw an EvalError.
if source_string != code_string {
return false;
}
source_string
},
}
};
global
.get_csp_list()
.is_js_evaluation_allowed(global, &source_string)
}
}
impl fmt::Display for TrustedScript {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.data)
}
}
impl TrustedScriptMethods<crate::DomTypeHolder> for TrustedScript {
/// <https://www.w3.org/TR/trusted-types/#trustedscript-stringification-behavior>
fn Stringifier(&self) -> DOMString {
self.data.clone()
}
/// <https://www.w3.org/TR/trusted-types/#dom-trustedscript-tojson>
fn ToJSON(&self) -> DOMString {
self.data.clone()
}
}