mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement attribute and property lookup for Trusted Types (#36422)
These algorithms are used to check whether an attribute/property can accept a Trusted Type. Part of #36258 Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
parent
2c7aeca404
commit
0aa08042d5
7 changed files with 143 additions and 192 deletions
|
@ -4,6 +4,7 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use html5ever::{LocalName, Namespace, QualName, local_name, namespace_url, ns};
|
||||||
use js::rust::HandleValue;
|
use js::rust::HandleValue;
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyFactoryBinding::{
|
use crate::dom::bindings::codegen::Bindings::TrustedTypePolicyFactoryBinding::{
|
||||||
|
@ -85,6 +86,49 @@ impl TrustedTypePolicyFactory {
|
||||||
// Step 9: Return policy.
|
// Step 9: Return policy.
|
||||||
Ok(policy)
|
Ok(policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-get-trusted-type-data-for-attribute>
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
|
fn get_trusted_type_data_for_attribute(
|
||||||
|
element: QualName,
|
||||||
|
attribute: String,
|
||||||
|
attribute_namespace: Option<Namespace>,
|
||||||
|
) -> Option<DOMString> {
|
||||||
|
// Step 1: Let data be null.
|
||||||
|
let mut data = None;
|
||||||
|
// Step 2: If attributeNs is null, and attribute is the name of an event handler content attribute, then:
|
||||||
|
// TODO(36258): look up event handlers
|
||||||
|
// Step 3: Find the row in the following table, where element is in the first column,
|
||||||
|
// attributeNs is in the second column, and attribute is in the third column.
|
||||||
|
// If a matching row is found, set data to that row.
|
||||||
|
if element.ns == ns!(html) &&
|
||||||
|
element.local == local_name!("iframe") &&
|
||||||
|
attribute_namespace.is_none() &&
|
||||||
|
attribute == "srcdoc"
|
||||||
|
{
|
||||||
|
data = Some(DOMString::from("TrustedHTML"))
|
||||||
|
} else if element.ns == ns!(html) &&
|
||||||
|
element.local == local_name!("script") &&
|
||||||
|
attribute_namespace.is_none() &&
|
||||||
|
attribute == "src"
|
||||||
|
{
|
||||||
|
data = Some(DOMString::from("TrustedScriptURL"))
|
||||||
|
} else if element.ns == ns!(svg) &&
|
||||||
|
element.local == local_name!("script") &&
|
||||||
|
attribute_namespace.is_none() &&
|
||||||
|
attribute == "href"
|
||||||
|
{
|
||||||
|
data = Some(DOMString::from("TrustedScriptURL"))
|
||||||
|
} else if element.ns == ns!(svg) &&
|
||||||
|
element.local == local_name!("script") &&
|
||||||
|
attribute_namespace == Some(ns!(xlink)) &&
|
||||||
|
attribute == "href"
|
||||||
|
{
|
||||||
|
data = Some(DOMString::from("TrustedScriptURL"))
|
||||||
|
}
|
||||||
|
// Step 4: Return data.
|
||||||
|
data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrustedTypePolicyFactoryMethods<crate::DomTypeHolder> for TrustedTypePolicyFactory {
|
impl TrustedTypePolicyFactoryMethods<crate::DomTypeHolder> for TrustedTypePolicyFactory {
|
||||||
|
@ -135,23 +179,99 @@ impl TrustedTypePolicyFactoryMethods<crate::DomTypeHolder> for TrustedTypePolicy
|
||||||
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-getattributetype>
|
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-getattributetype>
|
||||||
fn GetAttributeType(
|
fn GetAttributeType(
|
||||||
&self,
|
&self,
|
||||||
_: DOMString,
|
tag_name: DOMString,
|
||||||
_: DOMString,
|
attribute: DOMString,
|
||||||
_: Option<DOMString>,
|
element_namespace: Option<DOMString>,
|
||||||
_: Option<DOMString>,
|
attribute_namespace: Option<DOMString>,
|
||||||
) -> Option<DOMString> {
|
) -> Option<DOMString> {
|
||||||
// TODO(36258): implement algorithm
|
// Step 1: Set localName to tagName in ASCII lowercase.
|
||||||
Some(DOMString::from("".to_string()))
|
let local_name = tag_name.to_ascii_lowercase();
|
||||||
|
// Step 2: Set attribute to attribute in ASCII lowercase.
|
||||||
|
let attribute = attribute.to_ascii_lowercase();
|
||||||
|
// Step 3: If elementNs is null or an empty string, set elementNs to HTML namespace.
|
||||||
|
let element_namespace = match element_namespace {
|
||||||
|
Some(namespace) if !namespace.is_empty() => Namespace::from(namespace),
|
||||||
|
Some(_) | None => ns!(html),
|
||||||
|
};
|
||||||
|
// Step 4: If attrNs is an empty string, set attrNs to null.
|
||||||
|
let attribute_namespace = match attribute_namespace {
|
||||||
|
Some(namespace) if !namespace.is_empty() => Some(Namespace::from(namespace)),
|
||||||
|
Some(_) | None => None,
|
||||||
|
};
|
||||||
|
// Step 5: Let interface be the element interface for localName and elementNs.
|
||||||
|
let interface = QualName::new(None, element_namespace, LocalName::from(local_name));
|
||||||
|
// Step 6: Let expectedType be null.
|
||||||
|
let mut expected_type = None;
|
||||||
|
// Step 7: Set attributeData to the result of Get Trusted Type data for attribute algorithm,
|
||||||
|
// with the following arguments: interface as element, attribute, attrNs
|
||||||
|
let attribute_data = TrustedTypePolicyFactory::get_trusted_type_data_for_attribute(
|
||||||
|
interface,
|
||||||
|
attribute,
|
||||||
|
attribute_namespace,
|
||||||
|
);
|
||||||
|
// Step 8: If attributeData is not null, then set expectedType to the interface’s name of
|
||||||
|
// the value of the fourth member of attributeData.
|
||||||
|
if let Some(trusted_type) = attribute_data {
|
||||||
|
expected_type = Some(trusted_type)
|
||||||
|
}
|
||||||
|
// Step 9: Return expectedType.
|
||||||
|
expected_type
|
||||||
}
|
}
|
||||||
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-getpropertytype>
|
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-getpropertytype>
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
fn GetPropertyType(
|
fn GetPropertyType(
|
||||||
&self,
|
&self,
|
||||||
_: DOMString,
|
tag_name: DOMString,
|
||||||
_: DOMString,
|
property: DOMString,
|
||||||
_: Option<DOMString>,
|
element_namespace: Option<DOMString>,
|
||||||
) -> Option<DOMString> {
|
) -> Option<DOMString> {
|
||||||
// TODO(36258): implement algorithm
|
// Step 1: Set localName to tagName in ASCII lowercase.
|
||||||
Some(DOMString::from("".to_string()))
|
let local_name = tag_name.to_ascii_lowercase();
|
||||||
|
// Step 2: If elementNs is null or an empty string, set elementNs to HTML namespace.
|
||||||
|
let element_namespace = match element_namespace {
|
||||||
|
Some(namespace) if !namespace.is_empty() => Namespace::from(namespace),
|
||||||
|
Some(_) | None => ns!(html),
|
||||||
|
};
|
||||||
|
// Step 3: Let interface be the element interface for localName and elementNs.
|
||||||
|
let interface = QualName::new(None, element_namespace, LocalName::from(local_name));
|
||||||
|
// Step 4: Let expectedType be null.
|
||||||
|
let mut expected_type = None;
|
||||||
|
// Step 5: Find the row in the following table, where the first column is "*" or interface’s name,
|
||||||
|
// and property is in the second column. If a matching row is found, set expectedType to
|
||||||
|
// the interface’s name of the value of the third column.
|
||||||
|
let property = property.str();
|
||||||
|
if interface.ns == ns!(html) &&
|
||||||
|
interface.local == local_name!("iframe") &&
|
||||||
|
property == "srcdoc"
|
||||||
|
{
|
||||||
|
expected_type = Some(DOMString::from("TrustedHTML"))
|
||||||
|
} else if interface.ns == ns!(html) &&
|
||||||
|
interface.local == local_name!("script") &&
|
||||||
|
property == "innerText"
|
||||||
|
{
|
||||||
|
expected_type = Some(DOMString::from("TrustedScript"))
|
||||||
|
} else if interface.ns == ns!(html) &&
|
||||||
|
interface.local == local_name!("script") &&
|
||||||
|
property == "src"
|
||||||
|
{
|
||||||
|
expected_type = Some(DOMString::from("TrustedScriptURL"))
|
||||||
|
} else if interface.ns == ns!(html) &&
|
||||||
|
interface.local == local_name!("script") &&
|
||||||
|
property == "text"
|
||||||
|
{
|
||||||
|
expected_type = Some(DOMString::from("TrustedScript"))
|
||||||
|
} else if interface.ns == ns!(html) &&
|
||||||
|
interface.local == local_name!("script") &&
|
||||||
|
property == "textContent"
|
||||||
|
{
|
||||||
|
expected_type = Some(DOMString::from("TrustedScript"))
|
||||||
|
} else if property == "innerHTML" {
|
||||||
|
expected_type = Some(DOMString::from("TrustedHTML"))
|
||||||
|
} else if property == "outerHTML" {
|
||||||
|
expected_type = Some(DOMString::from("TrustedHTML"))
|
||||||
|
}
|
||||||
|
// Step 6: Return expectedType.
|
||||||
|
expected_type
|
||||||
}
|
}
|
||||||
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-defaultpolicy>
|
/// <https://www.w3.org/TR/trusted-types/#dom-trustedtypepolicyfactory-defaultpolicy>
|
||||||
fn GetDefaultPolicy(&self) -> Option<DomRoot<TrustedTypePolicy>> {
|
fn GetDefaultPolicy(&self) -> Option<DomRoot<TrustedTypePolicy>> {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[HTMLElement-generic.html]
|
[HTMLElement-generic.html]
|
||||||
expected: ERROR
|
|
||||||
[TT enabled: script.src\n = String on a\n connected element\n ]
|
[TT enabled: script.src\n = String on a\n connected element\n ]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -71,3 +70,15 @@
|
||||||
|
|
||||||
[TT enabled: script.textContent\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive]
|
[TT enabled: script.textContent\n = String on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[TT enabled: script.src\n = TrustedScript on a\n connected element\n ]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[TT enabled: script.src\n = TrustedScript on a\n non-connected element\n ]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[TT enabled: script.src\n = TrustedScript on a\n connected element\n after removing the "require-trusted-types-for 'script' directive]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[TT enabled: script.src\n = TrustedScript on a\n non-connected element\n after removing the "require-trusted-types-for 'script' directive]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
[TrustedTypePolicyFactory-getAttributeType-namespace.html]
|
|
||||||
[0: getAttributeType with full namespace info.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType with element namespace and empty attribute namespace]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType without namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType with undefined and empty namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType with empty and undefined namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType with empty namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[0: getAttributeType with element namespace and empty attribute namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with full namespace info.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with element namespace and empty attribute namespace]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType without namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with undefined and empty namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with empty and undefined namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with empty namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[1: getAttributeType with element namespace and empty attribute namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with full namespace info.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with element namespace and empty attribute namespace]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType without namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with undefined and empty namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with empty and undefined namespace.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with empty namespaces.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[2: getAttributeType with element namespace and empty attribute namespace.]
|
|
||||||
expected: FAIL
|
|
|
@ -1,12 +0,0 @@
|
||||||
[TrustedTypePolicyFactory-getAttributeType-svg.html]
|
|
||||||
[trustedTypes.getAttributeType html script[href\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[trustedTypes.getAttributeType svg script[href\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[trustedTypes.getAttributeType svg script[href\] xlink href]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[trustedTypes.getAttributeType svg script[href\] other href]
|
|
||||||
expected: FAIL
|
|
|
@ -7,63 +7,3 @@
|
||||||
|
|
||||||
[getAttributeType(\n "mrow",\n "onmousedown",\n "http://www.w3.org/1998/Math/MathML",\n "null") == "TrustedScript"]
|
[getAttributeType(\n "mrow",\n "onmousedown",\n "http://www.w3.org/1998/Math/MathML",\n "null") == "TrustedScript"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[getAttributeType(\n "IFRAME",\n "srcdoc",\n "http://www.w3.org/1999/xhtml",\n "null") == "TrustedHTML"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "SCRIPT",\n "src",\n "http://www.w3.org/1999/xhtml",\n "null") == "TrustedScriptURL"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "script",\n "href",\n "http://www.w3.org/2000/svg",\n "null") == "TrustedScriptURL"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "script",\n "href",\n "http://www.w3.org/2000/svg",\n "http://www.w3.org/1999/xlink") == "TrustedScriptURL"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "foo",\n "onmouseup",\n "https://example.com/namespace",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "DIV",\n "onclick",\n "http://www.w3.org/1999/xhtml",\n "https://example.com/namespace") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "DIV",\n "ondoesnotexist",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "DIV",\n "data-onclick",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "DIV",\n "srcdoc",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "iframe",\n "srcdoc",\n "https://example.com/namespace",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "IFRAME",\n "srcdoc",\n "http://www.w3.org/1999/xhtml",\n "https://example.com/namespace") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "IFRAME",\n "data-srcdoc",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "DIV",\n "src",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "script",\n "src",\n "https://example.com/namespace",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "SCRIPT",\n "src",\n "http://www.w3.org/1999/xhtml",\n "https://example.com/namespace") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "SCRIPT",\n "data-src",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "g",\n "href",\n "http://www.w3.org/2000/svg",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "SCRIPT",\n "href",\n "http://www.w3.org/1999/xhtml",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "script",\n "href",\n "http://www.w3.org/2000/svg",\n "https://example.com/namespace") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType(\n "script",\n "src",\n "http://www.w3.org/2000/svg",\n "null") == "null"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,48 +1,9 @@
|
||||||
[TrustedTypePolicyFactory-getPropertyType.tentative.html]
|
[TrustedTypePolicyFactory-getPropertyType.tentative.html]
|
||||||
[sanity check trustedTypes.getPropertyType for the HTML script element.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[sanity check trustedTypes.getAttributeType.]
|
[sanity check trustedTypes.getAttributeType.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[getPropertyType tests adapted from w3c/trusted-types polyfill]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType tests adapted from w3c/trusted-types polyfill]
|
[getAttributeType tests adapted from w3c/trusted-types polyfill]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[iframe.srcDoc is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[IFRAME.srcDoc is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[iFrAmE.srcDoc is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[iframe.SRCDOC is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[IFRAME.SRCDOC is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[iFrAmE.SRCDOC is maybe defined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getPropertyType vs getAttributeType for event handler.]
|
[getPropertyType vs getAttributeType for event handler.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ASCII case-insensitivity of tag name and attribute parameters]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getPropertyType with an explicit elementNs parameter]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType with explicit elementNs and attrNs parameters]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType with qualified attribute name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getPropertyType/getAttributeType with explicit null elementNs/attrNs]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[legacy-trusted-script-urls.html]
|
|
||||||
[getPropertyType() with legacy TrustedScriptURLs properties return null.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getAttributeType() with legacy TrustedScriptURLs attributes return null.]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue