diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 88f902f425d..980b08f2e08 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -116,6 +116,7 @@ pub struct Preferences { pub dom_testperf_enabled: bool, // https://testutils.spec.whatwg.org#availability pub dom_testutils_enabled: bool, + pub dom_trusted_types_enabled: bool, /// Enable the [URLPattern] API. /// /// [URLPattern]: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern @@ -290,6 +291,7 @@ impl Preferences { dom_testing_html_input_element_select_files_enabled: false, dom_testperf_enabled: false, dom_testutils_enabled: false, + dom_trusted_types_enabled: false, dom_urlpattern_enabled: false, dom_webgl2_enabled: false, dom_webgpu_enabled: false, diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index d0d7830e2bb..7d3c65dad2f 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -125,6 +125,7 @@ use crate::dom::promise::Promise; use crate::dom::readablestream::ReadableStream; use crate::dom::serviceworker::ServiceWorker; use crate::dom::serviceworkerregistration::ServiceWorkerRegistration; +use crate::dom::trustedtypepolicyfactory::TrustedTypePolicyFactory; use crate::dom::underlyingsourcecontainer::UnderlyingSourceType; #[cfg(feature = "webgpu")] use crate::dom::webgpu::gpudevice::GPUDevice; @@ -3300,6 +3301,16 @@ impl GlobalScope { .borrow_mut() .remove(&callback_id) } + + pub(crate) fn trusted_types(&self, can_gc: CanGc) -> DomRoot { + if let Some(window) = self.downcast::() { + return window.TrustedTypes(can_gc); + } + if let Some(worker) = self.downcast::() { + return worker.TrustedTypes(can_gc); + } + unreachable!(); + } } /// Returns the Rust global scope from a JS global object. diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 0b32dafd4e1..417bcface58 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -575,6 +575,11 @@ pub(crate) mod touchlist; pub(crate) mod trackevent; pub(crate) mod transitionevent; pub(crate) mod treewalker; +pub(crate) mod trustedhtml; +pub(crate) mod trustedscript; +pub(crate) mod trustedscripturl; +pub(crate) mod trustedtypepolicy; +pub(crate) mod trustedtypepolicyfactory; pub(crate) mod uievent; pub(crate) mod underlyingsourcecontainer; pub(crate) mod url; diff --git a/components/script/dom/trustedhtml.rs b/components/script/dom/trustedhtml.rs new file mode 100644 index 00000000000..07298601f2f --- /dev/null +++ b/components/script/dom/trustedhtml.rs @@ -0,0 +1,45 @@ +/* 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 dom_struct::dom_struct; + +use crate::dom::bindings::codegen::Bindings::TrustedHTMLBinding::TrustedHTMLMethods; +use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::script_runtime::CanGc; + +#[dom_struct] +pub struct TrustedHTML { + reflector_: Reflector, + + data: String, +} + +impl TrustedHTML { + fn new_inherited(data: String) -> Self { + Self { + reflector_: Reflector::new(), + data, + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new(data: String, global: &GlobalScope, can_gc: CanGc) -> DomRoot { + reflect_dom_object(Box::new(Self::new_inherited(data)), global, can_gc) + } +} + +impl TrustedHTMLMethods for TrustedHTML { + /// + fn Stringifier(&self) -> DOMString { + DOMString::from(&*self.data) + } + + /// + fn ToJSON(&self) -> DOMString { + DOMString::from(&*self.data) + } +} diff --git a/components/script/dom/trustedscript.rs b/components/script/dom/trustedscript.rs new file mode 100644 index 00000000000..5ce51c24989 --- /dev/null +++ b/components/script/dom/trustedscript.rs @@ -0,0 +1,45 @@ +/* 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 dom_struct::dom_struct; + +use crate::dom::bindings::codegen::Bindings::TrustedScriptBinding::TrustedScriptMethods; +use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::script_runtime::CanGc; + +#[dom_struct] +pub struct TrustedScript { + reflector_: Reflector, + + data: String, +} + +impl TrustedScript { + fn new_inherited(data: String) -> Self { + Self { + reflector_: Reflector::new(), + data, + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new(data: String, global: &GlobalScope, can_gc: CanGc) -> DomRoot { + reflect_dom_object(Box::new(Self::new_inherited(data)), global, can_gc) + } +} + +impl TrustedScriptMethods for TrustedScript { + /// + fn Stringifier(&self) -> DOMString { + DOMString::from(&*self.data) + } + + /// + fn ToJSON(&self) -> DOMString { + DOMString::from(&*self.data) + } +} diff --git a/components/script/dom/trustedscripturl.rs b/components/script/dom/trustedscripturl.rs new file mode 100644 index 00000000000..01a82a4fff7 --- /dev/null +++ b/components/script/dom/trustedscripturl.rs @@ -0,0 +1,45 @@ +/* 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 dom_struct::dom_struct; + +use crate::dom::bindings::codegen::Bindings::TrustedScriptURLBinding::TrustedScriptURLMethods; +use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::script_runtime::CanGc; + +#[dom_struct] +pub struct TrustedScriptURL { + reflector_: Reflector, + + data: String, +} + +impl TrustedScriptURL { + fn new_inherited(data: String) -> Self { + Self { + reflector_: Reflector::new(), + data, + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new(data: String, global: &GlobalScope, can_gc: CanGc) -> DomRoot { + reflect_dom_object(Box::new(Self::new_inherited(data)), global, can_gc) + } +} + +impl TrustedScriptURLMethods for TrustedScriptURL { + /// + fn Stringifier(&self) -> DOMString { + DOMString::from(&*self.data) + } + + /// + fn ToJSON(&self) -> DOMString { + DOMString::from(&*self.data) + } +} diff --git a/components/script/dom/trustedtypepolicy.rs b/components/script/dom/trustedtypepolicy.rs new file mode 100644 index 00000000000..9cbeb25a83c --- /dev/null +++ b/components/script/dom/trustedtypepolicy.rs @@ -0,0 +1,77 @@ +/* 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 dom_struct::dom_struct; +use js::rust::HandleValue; + +use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyBinding::TrustedTypePolicyMethods; +use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::dom::trustedhtml::TrustedHTML; +use crate::dom::trustedscript::TrustedScript; +use crate::dom::trustedscripturl::TrustedScriptURL; +use crate::script_runtime::{CanGc, JSContext}; + +#[dom_struct] +pub struct TrustedTypePolicy { + reflector_: Reflector, + + name: String, +} + +impl TrustedTypePolicy { + fn new_inherited(name: String) -> Self { + Self { + reflector_: Reflector::new(), + name, + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new(name: String, global: &GlobalScope, can_gc: CanGc) -> DomRoot { + reflect_dom_object(Box::new(Self::new_inherited(name)), global, can_gc) + } +} + +impl TrustedTypePolicyMethods for TrustedTypePolicy { + /// + fn Name(&self) -> DOMString { + DOMString::from(&*self.name) + } + /// + fn CreateHTML( + &self, + _: JSContext, + data: DOMString, + _: Vec, + can_gc: CanGc, + ) -> DomRoot { + // TODO(36258): handle arguments + TrustedHTML::new(data.to_string(), &self.global(), can_gc) + } + /// + fn CreateScript( + &self, + _: JSContext, + data: DOMString, + _: Vec, + can_gc: CanGc, + ) -> DomRoot { + // TODO(36258): handle arguments + TrustedScript::new(data.to_string(), &self.global(), can_gc) + } + /// + fn CreateScriptURL( + &self, + _: JSContext, + data: DOMString, + _: Vec, + can_gc: CanGc, + ) -> DomRoot { + // TODO(36258): handle arguments + TrustedScriptURL::new(data.to_string(), &self.global(), can_gc) + } +} diff --git a/components/script/dom/trustedtypepolicyfactory.rs b/components/script/dom/trustedtypepolicyfactory.rs new file mode 100644 index 00000000000..02bafb021f1 --- /dev/null +++ b/components/script/dom/trustedtypepolicyfactory.rs @@ -0,0 +1,160 @@ +/* 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::cell::RefCell; + +use dom_struct::dom_struct; +use js::rust::HandleValue; + +use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyFactoryBinding::{ + TrustedTypePolicyFactoryMethods, TrustedTypePolicyOptions, +}; +use crate::dom::bindings::conversions::root_from_object; +use crate::dom::bindings::error::{Error, Fallible}; +use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::dom::trustedhtml::TrustedHTML; +use crate::dom::trustedscript::TrustedScript; +use crate::dom::trustedscripturl::TrustedScriptURL; +use crate::dom::trustedtypepolicy::TrustedTypePolicy; +use crate::script_runtime::{CanGc, JSContext}; + +#[dom_struct] +pub struct TrustedTypePolicyFactory { + reflector_: Reflector, + + default_policy: MutNullableDom, + policy_names: RefCell>, +} + +impl TrustedTypePolicyFactory { + fn new_inherited() -> Self { + Self { + reflector_: Reflector::new(), + default_policy: Default::default(), + policy_names: RefCell::new(vec![]), + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot { + reflect_dom_object(Box::new(Self::new_inherited()), global, can_gc) + } + + /// + fn create_trusted_type_policy( + &self, + policy_name: String, + _options: &TrustedTypePolicyOptions, + global: &GlobalScope, + can_gc: CanGc, + ) -> Fallible> { + // TODO(36258): implement proper CSP check + // Step 1: Let allowedByCSP be the result of executing Should Trusted Type policy creation be blocked by + // Content Security Policy? algorithm with global, policyName and factory’s created policy names value. + let allowed_by_csp = true; + + // Step 2: If allowedByCSP is "Blocked", throw a TypeError and abort further steps. + if !allowed_by_csp { + return Err(Error::Type("Not allowed by CSP".to_string())); + } + + // Step 3: If policyName is default and the factory’s default policy value is not null, throw a TypeError + // and abort further steps. + if policy_name == "default" && self.default_policy.get().is_some() { + return Err(Error::Type( + "Already set default policy for factory".to_string(), + )); + } + + // Step 4: Let policy be a new TrustedTypePolicy object. + // Step 5: Set policy’s name property value to policyName. + let policy = TrustedTypePolicy::new(policy_name.clone(), global, can_gc); + // Step 6: Set policy’s options value to «[ "createHTML" -> + // options["createHTML", "createScript" -> options["createScript", + // "createScriptURL" -> options["createScriptURL" ]». + // TODO(36258): implement step 6 + // Step 7: If the policyName is default, set the factory’s default policy value to policy. + if policy_name == "default" { + self.default_policy.set(Some(&policy)) + } + // Step 8: Append policyName to factory’s created policy names. + self.policy_names.borrow_mut().push(policy_name); + // Step 9: Return policy. + Ok(policy) + } +} + +impl TrustedTypePolicyFactoryMethods for TrustedTypePolicyFactory { + /// + fn CreatePolicy( + &self, + policy_name: DOMString, + options: &TrustedTypePolicyOptions, + can_gc: CanGc, + ) -> Fallible> { + self.create_trusted_type_policy(policy_name.to_string(), options, &self.global(), can_gc) + } + /// + #[allow(unsafe_code)] + fn IsHTML(&self, cx: JSContext, value: HandleValue) -> bool { + if !value.get().is_object() { + return false; + } + rooted!(in(*cx) let object = value.to_object()); + unsafe { root_from_object::(object.get(), *cx).is_ok() } + } + /// + #[allow(unsafe_code)] + fn IsScript(&self, cx: JSContext, value: HandleValue) -> bool { + if !value.get().is_object() { + return false; + } + rooted!(in(*cx) let object = value.to_object()); + unsafe { root_from_object::(object.get(), *cx).is_ok() } + } + /// + #[allow(unsafe_code)] + fn IsScriptURL(&self, cx: JSContext, value: HandleValue) -> bool { + if !value.get().is_object() { + return false; + } + rooted!(in(*cx) let object = value.to_object()); + unsafe { root_from_object::(object.get(), *cx).is_ok() } + } + /// + fn EmptyHTML(&self, can_gc: CanGc) -> DomRoot { + TrustedHTML::new("".to_string(), &self.global(), can_gc) + } + /// + fn EmptyScript(&self, can_gc: CanGc) -> DomRoot { + TrustedScript::new("".to_string(), &self.global(), can_gc) + } + /// + fn GetAttributeType( + &self, + _: DOMString, + _: DOMString, + _: Option, + _: Option, + ) -> Option { + // TODO(36258): implement algorithm + Some(DOMString::from("".to_string())) + } + /// + fn GetPropertyType( + &self, + _: DOMString, + _: DOMString, + _: Option, + ) -> Option { + // TODO(36258): implement algorithm + Some(DOMString::from("".to_string())) + } + /// + fn GetDefaultPolicy(&self) -> Option> { + self.default_policy.get() + } +} diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index aff9d181081..fc9c4bf88d2 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -145,6 +145,7 @@ use crate::dom::selection::Selection; use crate::dom::storage::Storage; #[cfg(feature = "bluetooth")] use crate::dom::testrunner::TestRunner; +use crate::dom::trustedtypepolicyfactory::TrustedTypePolicyFactory; use crate::dom::types::UIEvent; use crate::dom::webglrenderingcontext::WebGLCommandSender; #[cfg(feature = "webgpu")] @@ -247,6 +248,7 @@ pub(crate) struct Window { session_storage: MutNullableDom, local_storage: MutNullableDom, status: DomRefCell, + trusted_types: MutNullableDom, /// For sending timeline markers. Will be ignored if /// no devtools server @@ -1696,6 +1698,11 @@ impl WindowMethods for Window { self.as_global_scope() .structured_clone(cx, value, options, retval) } + + fn TrustedTypes(&self, can_gc: CanGc) -> DomRoot { + self.trusted_types + .or_init(|| TrustedTypePolicyFactory::new(self.as_global_scope(), can_gc)) + } } impl Window { @@ -2922,6 +2929,7 @@ impl Window { layout_marker: DomRefCell::new(Rc::new(Cell::new(true))), current_event: DomRefCell::new(None), theme: Cell::new(PrefersColorScheme::Light), + trusted_types: Default::default(), }); unsafe { diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 3937f8fbedb..7009f51e29a 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -52,6 +52,7 @@ use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use crate::dom::globalscope::GlobalScope; use crate::dom::performance::Performance; use crate::dom::promise::Promise; +use crate::dom::trustedtypepolicyfactory::TrustedTypePolicyFactory; #[cfg(feature = "webgpu")] use crate::dom::webgpu::identityhub::IdentityHub; use crate::dom::window::{base64_atob, base64_btoa}; @@ -122,6 +123,7 @@ pub(crate) struct WorkerGlobalScope { #[no_trace] navigation_start: CrossProcessInstant, performance: MutNullableDom, + trusted_types: MutNullableDom, /// A [`TimerScheduler`] used to schedule timers for this [`WorkerGlobalScope`]. /// Timers are handled in the service worker event loop. @@ -184,6 +186,7 @@ impl WorkerGlobalScope { performance: Default::default(), timer_scheduler: RefCell::default(), insecure_requests_policy, + trusted_types: Default::default(), } } @@ -477,6 +480,14 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope { self.upcast::() .structured_clone(cx, value, options, retval) } + + /// + fn TrustedTypes(&self, can_gc: CanGc) -> DomRoot { + self.trusted_types.or_init(|| { + let global_scope = self.upcast::(); + TrustedTypePolicyFactory::new(global_scope, can_gc) + }) + } } impl WorkerGlobalScope { diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index a3adf0f39ab..2c94c445778 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -575,6 +575,14 @@ DOMInterfaces = { 'canGc': ['ParentNode', 'PreviousNode', 'NextNode', 'FirstChild', 'LastChild', 'PreviousSibling', 'NextSibling'] }, +'TrustedTypePolicy': { + 'canGc': ['CreateHTML', 'CreateScript', 'CreateScriptURL'] +}, + +'TrustedTypePolicyFactory': { + 'canGc': ['CreatePolicy', 'EmptyHTML', 'EmptyScript'] +}, + 'URL': { 'weakReferenceable': True, 'canGc': ['Parse', 'SearchParams'], @@ -590,7 +598,7 @@ DOMInterfaces = { }, 'Window': { - 'canGc': ['Stop', 'Fetch', 'Scroll', 'Scroll_','ScrollBy', 'ScrollBy_', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap'], + 'canGc': ['Stop', 'Fetch', 'Scroll', 'Scroll_','ScrollBy', 'ScrollBy_', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap', 'TrustedTypes'], 'inRealms': ['Fetch', 'GetOpener'], 'additionalTraits': ['crate::interfaces::WindowHelpers'], }, @@ -602,7 +610,7 @@ DOMInterfaces = { 'WorkerGlobalScope': { 'inRealms': ['Fetch'], - 'canGc': ['Fetch', 'CreateImageBitmap', 'ImportScripts'], + 'canGc': ['Fetch', 'CreateImageBitmap', 'ImportScripts', 'TrustedTypes'], }, 'Worklet': { diff --git a/components/script_bindings/webidls/TrustedHTML.webidl b/components/script_bindings/webidls/TrustedHTML.webidl new file mode 100644 index 00000000000..37fb18bd5e1 --- /dev/null +++ b/components/script_bindings/webidls/TrustedHTML.webidl @@ -0,0 +1,13 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://www.w3.org/TR/trusted-types/#trusted-html + */ + +[Exposed=(Window,Worker), Pref="dom_trusted_types_enabled"] +interface TrustedHTML { + stringifier; + DOMString toJSON(); +}; diff --git a/components/script_bindings/webidls/TrustedScript.webidl b/components/script_bindings/webidls/TrustedScript.webidl new file mode 100644 index 00000000000..3dbee643ddf --- /dev/null +++ b/components/script_bindings/webidls/TrustedScript.webidl @@ -0,0 +1,13 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://www.w3.org/TR/trusted-types/#trusted-script + */ + +[Exposed=(Window,Worker), Pref="dom_trusted_types_enabled"] +interface TrustedScript { + stringifier; + DOMString toJSON(); +}; diff --git a/components/script_bindings/webidls/TrustedScriptURL.webidl b/components/script_bindings/webidls/TrustedScriptURL.webidl new file mode 100644 index 00000000000..b5fd0249eba --- /dev/null +++ b/components/script_bindings/webidls/TrustedScriptURL.webidl @@ -0,0 +1,13 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://www.w3.org/TR/trusted-types/#trused-script-url + */ + +[Exposed=(Window,Worker), Pref="dom_trusted_types_enabled"] +interface TrustedScriptURL { + stringifier; + DOMString toJSON(); +}; diff --git a/components/script_bindings/webidls/TrustedTypePolicy.webidl b/components/script_bindings/webidls/TrustedTypePolicy.webidl new file mode 100644 index 00000000000..e9bfa158795 --- /dev/null +++ b/components/script_bindings/webidls/TrustedTypePolicy.webidl @@ -0,0 +1,15 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://www.w3.org/TR/trusted-types/#trusted-type-policy + */ + +[Exposed=(Window,Worker), Pref="dom_trusted_types_enabled"] +interface TrustedTypePolicy { + readonly attribute DOMString name; + TrustedHTML createHTML(DOMString input, any... arguments); + TrustedScript createScript(DOMString input, any... arguments); + TrustedScriptURL createScriptURL(DOMString input, any... arguments); +}; diff --git a/components/script_bindings/webidls/TrustedTypePolicyFactory.webidl b/components/script_bindings/webidls/TrustedTypePolicyFactory.webidl new file mode 100644 index 00000000000..a568ec437f4 --- /dev/null +++ b/components/script_bindings/webidls/TrustedTypePolicyFactory.webidl @@ -0,0 +1,38 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://www.w3.org/TR/trusted-types/#trusted-type-policy-factory + */ + +[Exposed=(Window,Worker), Pref="dom_trusted_types_enabled"] +interface TrustedTypePolicyFactory { + [Throws] + TrustedTypePolicy createPolicy( + DOMString policyName, optional TrustedTypePolicyOptions policyOptions = {}); + boolean isHTML(any value); + boolean isScript(any value); + boolean isScriptURL(any value); + readonly attribute TrustedHTML emptyHTML; + readonly attribute TrustedScript emptyScript; + DOMString? getAttributeType( + DOMString tagName, + DOMString attribute, + optional DOMString? elementNs = "", + optional DOMString? attrNs = ""); + DOMString? getPropertyType( + DOMString tagName, + DOMString property, + optional DOMString? elementNs = ""); + readonly attribute TrustedTypePolicy? defaultPolicy; +}; + +dictionary TrustedTypePolicyOptions { + CreateHTMLCallback createHTML; + CreateScriptCallback createScript; + CreateScriptURLCallback createScriptURL; +}; +callback CreateHTMLCallback = DOMString? (DOMString input, any... arguments); +callback CreateScriptCallback = DOMString? (DOMString input, any... arguments); +callback CreateScriptURLCallback = USVString? (DOMString input, any... arguments); diff --git a/components/script_bindings/webidls/WindowOrWorkerGlobalScope.webidl b/components/script_bindings/webidls/WindowOrWorkerGlobalScope.webidl index d9204c11774..4ca7b1f2de1 100644 --- a/components/script_bindings/webidls/WindowOrWorkerGlobalScope.webidl +++ b/components/script_bindings/webidls/WindowOrWorkerGlobalScope.webidl @@ -45,5 +45,10 @@ partial interface mixin WindowOrWorkerGlobalScope { readonly attribute boolean isSecureContext; }; +// https://www.w3.org/TR/trusted-types/#extensions-to-the-windoworworkerglobalscope-interface +partial interface mixin WindowOrWorkerGlobalScope { + readonly attribute TrustedTypePolicyFactory trustedTypes; +}; + Window includes WindowOrWorkerGlobalScope; WorkerGlobalScope includes WindowOrWorkerGlobalScope; diff --git a/ports/servoshell/prefs.rs b/ports/servoshell/prefs.rs index 0f80f324d24..19420b0325b 100644 --- a/ports/servoshell/prefs.rs +++ b/ports/servoshell/prefs.rs @@ -558,6 +558,7 @@ pub(crate) fn parse_command_line_arguments(args: Vec) -> ArgumentParsing "dom_resize_observer_enabled", "dom_serviceworker_enabled", "dom_svg_enabled", + "dom_trusted_types_enabled", "dom_webgl2_enabled", "dom_webgpu_enabled", "dom_xpath_enabled", diff --git a/python/tidy/tidy.py b/python/tidy/tidy.py index dae69af21be..fe44be23df8 100644 --- a/python/tidy/tidy.py +++ b/python/tidy/tidy.py @@ -80,6 +80,7 @@ WEBIDL_STANDARDS = [ b"//dev.w3.org/csswg", b"//dev.w3.org/fxtf", b"//dvcs.w3.org/hg", + b"//www.w3.org/TR/trusted-types/", b"//dom.spec.whatwg.org", b"//drafts.csswg.org", b"//drafts.css-houdini.org", diff --git a/tests/wpt/meta/__dir__.ini b/tests/wpt/meta/__dir__.ini index 6b2e8f4dbfa..4f66fa65008 100644 --- a/tests/wpt/meta/__dir__.ini +++ b/tests/wpt/meta/__dir__.ini @@ -7,6 +7,7 @@ prefs: [ "dom_resize_observer_enabled:true", "dom_serviceworker_enabled:true", "dom_testutils_enabled:true", + "dom_trusted_types_enabled:true", "dom_urlpattern_enabled:true", "dom_xpath_enabled:true", "layout_grid_enabled:true", diff --git a/tests/wpt/meta/html/dom/idlharness.https.html.ini b/tests/wpt/meta/html/dom/idlharness.https.html.ini index 12044351c9e..a7c7cec2568 100644 --- a/tests/wpt/meta/html/dom/idlharness.https.html.ini +++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini @@ -1649,12 +1649,6 @@ [Element interface: calling setHTMLUnsafe((TrustedHTML or DOMString)) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "innerHTML" with the proper type] - expected: FAIL - - [Element interface: document.createElement("noscript") must inherit property "outerHTML" with the proper type] - expected: FAIL - [ShadowRoot interface: operation setHTMLUnsafe((TrustedHTML or DOMString))] expected: FAIL @@ -4562,12 +4556,6 @@ [DOMStringList interface: calling contains(DOMString) on location.ancestorOrigins with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "innerHTML" with the proper type] - expected: FAIL - - [Element interface: document.createElement("noscript") must inherit property "outerHTML" with the proper type] - expected: FAIL - [TextTrack interface: attribute inBandMetadataTrackDispatchType] expected: FAIL @@ -5825,12 +5813,6 @@ [OffscreenCanvasRenderingContext2D interface: attribute lang] expected: FAIL - [Element interface: document.createElement("div") must inherit property "innerHTML" with the proper type] - expected: FAIL - - [Element interface: document.createElement("div") must inherit property "outerHTML" with the proper type] - expected: FAIL - [idlharness.https.html?include=HTML.+] [HTMLAllCollection interface: existence and properties of interface object] @@ -6313,9 +6295,6 @@ [HTMLIFrameElement interface: attribute marginWidth] expected: FAIL - [HTMLIFrameElement interface: document.createElement("iframe") must inherit property "srcdoc" with the proper type] - expected: FAIL - [HTMLIFrameElement interface: document.createElement("iframe") must inherit property "allow" with the proper type] expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-block-eval-function-constructor.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-block-eval-function-constructor.html.ini index 86a4bed8d74..21bc9787f45 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-block-eval-function-constructor.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-block-eval-function-constructor.html.ini @@ -1,2 +1,18 @@ [DedicatedWorker-block-eval-function-constructor.html] - expected: ERROR + [Blocked eval in DedicatedWorkerGlobalScope.] + expected: FAIL + + [Blocked indirect eval in DedicatedWorkerGlobalScope.] + expected: FAIL + + [Blocked Function constructor in DedicatedWorkerGlobalScope.] + expected: FAIL + + [Blocked AsyncFunction constructor in DedicatedWorkerGlobalScope.] + expected: FAIL + + [Blocked GeneratorFunction constructor in DedicatedWorkerGlobalScope.] + expected: FAIL + + [Blocked AsyncGeneratorFunction constructor in DedicatedWorkerGlobalScope.] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html.ini index 59b0350d786..87e1655ef2a 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html.ini @@ -1,2 +1,3 @@ [DedicatedWorker-constructor-from-DedicatedWorker.html] - expected: TIMEOUT + [Creating a Worker from a string should throw (dedicated worker scope)] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-constructor.https.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-constructor.https.html.ini index 6c1d94e2d98..aee3766a47f 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-constructor.https.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-constructor.https.html.ini @@ -1,2 +1,6 @@ [DedicatedWorker-constructor.https.html] - expected: ERROR + [Block Worker creation via string] + expected: FAIL + + [Create Worker via string with default policy.] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-eval.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-eval.html.ini index 8026b3c0e0c..87f7fc65af0 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-eval.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-eval.html.ini @@ -1,2 +1,18 @@ [DedicatedWorker-eval.html] - expected: ERROR + [eval(string) in dedicated worker] + expected: FAIL + + [indirect eval(string) in dedicated worker] + expected: FAIL + + [eval(TrustedScript) in dedicated worker] + expected: FAIL + + [indirect eval(TrustedScript) in dedicated worker] + expected: FAIL + + [eval(string) with default policy mutation in dedicated worker] + expected: FAIL + + [indirect eval(string) with default policy mutation in dedicated worker] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-importScripts.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-importScripts.html.ini index a1cbb3a7587..e74c768adc5 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-importScripts.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-importScripts.html.ini @@ -1,2 +1,24 @@ [DedicatedWorker-importScripts.html] - expected: ERROR + [importScripts with TrustedScriptURL works in dedicated worker] + expected: FAIL + + [importScripts with untrusted URLs throws in dedicated worker] + expected: FAIL + + [null is not a trusted script URL throws in dedicated worker] + expected: FAIL + + [importScripts with two URLs, both trusted, in dedicated worker] + expected: FAIL + + [importScripts with two URLs, both strings, in dedicated worker] + expected: FAIL + + [importScripts with two URLs, one trusted, in dedicated worker] + expected: FAIL + + [importScripts with untrusted URLs and default policy works in dedicated worker] + expected: FAIL + + [importScripts with one trusted and one untrusted URLs and default policy works in dedicated worker] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/DedicatedWorker-setTimeout-setInterval.html.ini b/tests/wpt/meta/trusted-types/DedicatedWorker-setTimeout-setInterval.html.ini index f8d0bee9f06..ae1a87b05b3 100644 --- a/tests/wpt/meta/trusted-types/DedicatedWorker-setTimeout-setInterval.html.ini +++ b/tests/wpt/meta/trusted-types/DedicatedWorker-setTimeout-setInterval.html.ini @@ -1,2 +1,7 @@ [DedicatedWorker-setTimeout-setInterval.html] - expected: ERROR + expected: TIMEOUT + [DedicatedWorkerGlobalScope.setTimeout assigned via default policy (successful Script transformation).] + expected: TIMEOUT + + [DedicatedWorkerGlobalScope.setInterval assigned via default policy (successful Script transformation).] + expected: TIMEOUT diff --git a/tests/wpt/meta/trusted-types/Document-write-appending-line-feed.html.ini b/tests/wpt/meta/trusted-types/Document-write-appending-line-feed.html.ini index df548f4eabb..0c12db6f4ab 100644 --- a/tests/wpt/meta/trusted-types/Document-write-appending-line-feed.html.ini +++ b/tests/wpt/meta/trusted-types/Document-write-appending-line-feed.html.ini @@ -1,2 +1,18 @@ [Document-write-appending-line-feed.html] - expected: ERROR + [document.write() with TrustedHTML arguments only.] + expected: FAIL + + [document.write() with String arguments only.] + expected: FAIL + + [document.write() with TrustedHTML for all but one argument.] + expected: FAIL + + [document.writeln() with TrustedHTML arguments only.] + expected: FAIL + + [document.writeln() with String arguments only.] + expected: FAIL + + [document.writeln() with TrustedHTML for all but one argument.] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/Document-write-exception-order.xhtml.ini b/tests/wpt/meta/trusted-types/Document-write-exception-order.xhtml.ini index f59f580019f..b779a38f615 100644 --- a/tests/wpt/meta/trusted-types/Document-write-exception-order.xhtml.ini +++ b/tests/wpt/meta/trusted-types/Document-write-exception-order.xhtml.ini @@ -1,4 +1,3 @@ [Document-write-exception-order.xhtml] - expected: ERROR [`document.write(string)` throws TypeError] expected: FAIL diff --git a/tests/wpt/meta/trusted-types/Document-write.html.ini b/tests/wpt/meta/trusted-types/Document-write.html.ini index 66d8e77f277..5e06965f59f 100644 --- a/tests/wpt/meta/trusted-types/Document-write.html.ini +++ b/tests/wpt/meta/trusted-types/Document-write.html.ini @@ -4,15 +4,3 @@ [document.writeln with html assigned via policy (successful transformation).] expected: FAIL - - [document.write(TrustedHTML, TrustedHTML)] - expected: FAIL - - [document.writeln(TrustedHTML, TrustedHTML)] - expected: FAIL - - [document.write(TrustedHTML, String)] - expected: FAIL - - [document.writeln(TrustedHTML, String)] - expected: FAIL diff --git a/tests/wpt/meta/trusted-types/Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html.ini b/tests/wpt/meta/trusted-types/Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html.ini index eea226de58b..08050dcf00f 100644 --- a/tests/wpt/meta/trusted-types/Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html.ini +++ b/tests/wpt/meta/trusted-types/Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html.ini @@ -1,2 +1,10 @@ [Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html] expected: ERROR + [setAttribute and setAttributeNode respect the element's node document's global's CSP;\n Element=iframe; Parent=div; Attribute=srcdoc] + expected: FAIL + + [setAttribute and setAttributeNode respect the element's node document's global's CSP;\n Element=script; Parent=div; Attribute=src] + expected: FAIL + + [setAttribute and setAttributeNode respect the element's node document's global's CSP;\n Element=script; Parent=svg; Attribute=href] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/Element-setAttribute-setAttributeNS-sinks.tentative.html.ini b/tests/wpt/meta/trusted-types/Element-setAttribute-setAttributeNS-sinks.tentative.html.ini index cdb3999590f..965d640d7b4 100644 --- a/tests/wpt/meta/trusted-types/Element-setAttribute-setAttributeNS-sinks.tentative.html.ini +++ b/tests/wpt/meta/trusted-types/Element-setAttribute-setAttributeNS-sinks.tentative.html.ini @@ -1,2 +1,21 @@ [Element-setAttribute-setAttributeNS-sinks.tentative.html] - expected: ERROR + [HTMLIFrameElement.setAttribute('srcdoc', plain_string)] + expected: FAIL + + [HTMLIFrameElement.setAttributeNS(null, 'srcdoc', plain_string)] + expected: FAIL + + [HTMLScriptElement.setAttribute('src', plain_string)] + expected: FAIL + + [HTMLScriptElement.setAttributeNS(null, 'src', plain_string)] + expected: FAIL + + [SVGScriptElement.setAttribute('href', plain_string)] + expected: FAIL + + [SVGScriptElement.setAttributeNS(null, 'href', plain_string)] + expected: FAIL + + [SVGScriptElement.setAttributeNS(NSURI_XLINK, 'href', plain_string)] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/GlobalEventHandlers-onclick.html.ini b/tests/wpt/meta/trusted-types/GlobalEventHandlers-onclick.html.ini index 88787de100a..3d8e44fa31b 100644 --- a/tests/wpt/meta/trusted-types/GlobalEventHandlers-onclick.html.ini +++ b/tests/wpt/meta/trusted-types/GlobalEventHandlers-onclick.html.ini @@ -1,2 +1,6 @@ [GlobalEventHandlers-onclick.html] - expected: ERROR + [a.setAttribute('onclick') sets an unsuitable trusted type.] + expected: FAIL + + [a.setAttribute('click') sets a test string.] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/HTMLElement-generic.html.ini b/tests/wpt/meta/trusted-types/HTMLElement-generic.html.ini index 852f2b7b4fd..80ff76472e5 100644 --- a/tests/wpt/meta/trusted-types/HTMLElement-generic.html.ini +++ b/tests/wpt/meta/trusted-types/HTMLElement-generic.html.ini @@ -1,2 +1,73 @@ [HTMLElement-generic.html] expected: ERROR + [TT enabled: script.src\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: script.src\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: div.innerHTML\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: div.innerHTML\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: iframe.srcdoc\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: iframe.srcdoc\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: script.text\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: script.text\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: script.innerText\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: script.innerText\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: script.textContent\n = String on a\n connected element\n ] + expected: FAIL + + [TT enabled: script.textContent\n = String on a\n non-connected element\n ] + expected: FAIL + + [TT enabled: script.src\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.src\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: div.innerHTML\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: div.innerHTML\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: iframe.srcdoc\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: iframe.srcdoc\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.text\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.text\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.innerText\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.innerText\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.textContent\n = String on a\n connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL + + [TT enabled: script.textContent\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/HTMLScriptElement-internal-slot.html.ini b/tests/wpt/meta/trusted-types/HTMLScriptElement-internal-slot.html.ini index d75ae00182d..37804067377 100644 --- a/tests/wpt/meta/trusted-types/HTMLScriptElement-internal-slot.html.ini +++ b/tests/wpt/meta/trusted-types/HTMLScriptElement-internal-slot.html.ini @@ -1,2 +1,6 @@ [HTMLScriptElement-internal-slot.html] - expected: ERROR + [Test TT application when manipulating