blob: df5dd8549d1913ed800768a04853e76c9a5c096d [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
// Like assert_array_equals, but disregard element order.
function assert_array_same(actual, expected) {
assert_array_equals(actual.sort(), expected.sort());
}
// Element names:
const elems_valid = [
"p", "template", "span", "custom-elements", "potato",
// Arguments will be stringified, so anything that stringifies to a valid
// name is also valid. (E.g. null => "null")
null, undefined, 123
];
const elems_invalid = [
"", [], ["*"], ["p"]
];
// Attribute names:
const attrs_valid = [
"href", "span",
];
const attrs_invalid = [
];
const all_elems = elems_valid.concat(elems_invalid);
const all_attrs = attrs_valid.concat(attrs_invalid);
for (const item of ["allowElements", "dropElements", "blockElements"]) {
test(t => {
const sanitizer = new Sanitizer({[item]: all_elems});
assert_array_same(sanitizer.getConfiguration()[item],
elems_valid.map(x => "" + x));
}, `Element names in config item: ${item}`);
}
for (const item of ["allowAttributes", "dropAttributes"]) {
test(t => {
const sanitizer = new Sanitizer(
{[item]: Object.fromEntries(all_attrs.map(x => [x, ["*"]]))});
assert_array_same(Object.keys(sanitizer.getConfiguration()[item]),
attrs_valid.map(x => "" + x));
}, `Attribute names in config item: ${item}`);
}
// Quick sanity tests for namespaced elements.
// Each test case is a duo or triplet:
// - a Sanitizer config string for an element.
// - an HTML probe string.
// - the expected result. (If different from the probe.)
const SVG_NS = "http://www.w3.org/2000/svg";
const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
[
[ "p", "<p>Hello</p>" ],
[ "svg", "<svg>Hello</svg>", "Hello" ],
[ { name: "svg", namespace: SVG_NS }, "<svg>Hello</svg>" ],
[ "math", "<math>Hello</math>", "Hello" ],
[ { name: "math", namespace: SVG_NS }, "<math>Hello</math>", "Hello" ],
[ { name: "math", namespace: MATHML_NS }, "<math>Hello</math>" ],
].forEach(([elem, probe, expected], index) => {
test(t => {
const sanitizer = new Sanitizer({allowElements: [elem],
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
allowUnknownMarkup: true});
const template = document.createElement("template");
template.setHTML(probe, {sanitizer});
assert_equals(template.innerHTML, expected ?? probe);
}, `Namespaced elements #${index}: allowElements: [${JSON.stringify(elem)}]`);
});
// Same for attributes:
const XLINK_NS = "http://www.w3.org/1999/xlink";
[
[ { name: "style", elements: "*" }, "<p style=\"bla\"></p>" ],
[ { name: "href", elements: "*" }, "<p href=\"bla\"></p>" ],
[ { name: "xlink:href", elements: "*" }, "<p xlink:href=\"bla\"></p>" ],
[ { name: "href", namespace: XLINK_NS, elements: "*" }, "<p xlink:href=\"bla\"></p>", "<p></p>" ],
[ { name: "href", namespace: XLINK_NS, elements: "*" }, "<p href='bla'></p>", "<p></p>" ],
[ { name: "href", elements: "*" }, "<p xlink:href='bla'></p>", "<p></p>" ],
].forEach(([attr, probe, expected], index) => {
test(t => {
const sanitizer = new Sanitizer({allowAttributes: [attr],
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
allowUnknownMarkup: true});
const template = document.createElement("template");
template.setHTML(probe, {sanitizer});
assert_equals(template.innerHTML, expected ?? probe);
}, `Namespaced attributes #${index}: allowAttributes: [${JSON.stringify(attr)}]`);
});
// Test for namespaced attribute inside namespace element
test(t => {
const probe = `<svg><a xlink:href="bla"></a></svg>`;
const sanitizer = new Sanitizer({
allowAttributes: [{ name: "href", namespace: XLINK_NS, elements: "*" }],
allowElements: [{ name: "svg", namespace: SVG_NS }, { name: "a", namespace: SVG_NS }],
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
allowUnknownMarkup: true});
const template = document.createElement("template");
template.setHTML(probe, {sanitizer});
assert_equals(template.innerHTML, probe);
}, "Namespaced attribute xlink:href inside SVG tree");
// Most element and attribute names are lower-cased, but "foreign content"
// like SVG and MathML have some mixed-cased names.
[
[ "feBlend", "<feBlend></feBlend>" ],
[ "feColorMatrix", "<feColorMatrix></feColorMatrix>" ],
[ "textPath", "<textPath></textPath>" ],
].forEach(([elem, probe], index) => {
const sanitize = (elem, probe) => {
const sanitizer = new Sanitizer({allowElements: [
{ name: "svg", namespace: SVG_NS },
{ name: elem, namespace: SVG_NS }
],
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
allowUnknownMarkup: true});
const template = document.createElement("template");
template.setHTML(`<svg>${probe}</svg>`, {sanitizer});
return template.content.firstElementChild.innerHTML;
};
test(t => {
assert_equals(sanitize(elem, probe), probe);
}, `Mixed-case element names #${index}: "svg:${elem}"`);
test(t => {
// Lowercase element names should be normalized to mixed-case.
assert_equals(sanitize(elem.toLowerCase(), probe), probe);
}, `Lower-case element names #${index}: "svg:${elem.toLowerCase()}"`);
test(t => {
assert_not_equals(sanitize(elem.toUpperCase(), probe), probe);
}, `Upper-case element names #${index}: "svg:${elem.toUpperCase()}"`);
test(t => {
const elems = ["svg:" + elem];
assert_array_equals(
new Sanitizer({allowElements: elems}).getConfiguration().allowElements,
elems);
}, `Mixed case element names #${index}: "${elem}" is preserved in config.`);
});
</script>
</body>
</html>