summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/trusted-types
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/trusted-types')
-rw-r--r--testing/web-platform/tests/trusted-types/DOMParser-parseFromString-regression.tentative.html32
-rw-r--r--testing/web-platform/tests/trusted-types/DOMParser-parseFromString.tentative.html20
-rw-r--r--testing/web-platform/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.tentative.html47
-rw-r--r--testing/web-platform/tests/trusted-types/Document-execCommand.tentative.html15
-rw-r--r--testing/web-platform/tests/trusted-types/Document-write.tentative.html14
-rw-r--r--testing/web-platform/tests/trusted-types/Element-insertAdjacentHTML.tentative.html36
-rw-r--r--testing/web-platform/tests/trusted-types/Element-insertAdjacentText.tentative.html37
-rw-r--r--testing/web-platform/tests/trusted-types/Element-outerHTML.tentative.html22
-rw-r--r--testing/web-platform/tests/trusted-types/Element-setAttribute.tentative.html44
-rw-r--r--testing/web-platform/tests/trusted-types/Element-setAttributeNS.tentative.html34
-rw-r--r--testing/web-platform/tests/trusted-types/GlobalEventHandlers-onclick.tentative.html92
-rw-r--r--testing/web-platform/tests/trusted-types/HTMLElement-generic.tentative.html82
-rw-r--r--testing/web-platform/tests/trusted-types/HTMLScriptElement-in-xhtml-document.tentative.https.xhtml19
-rw-r--r--testing/web-platform/tests/trusted-types/HTMLScriptElement-internal-slot.tentative.html159
-rw-r--r--testing/web-platform/tests/trusted-types/META.yml3
-rw-r--r--testing/web-platform/tests/trusted-types/Node-multiple-arguments.tentative.html66
-rw-r--r--testing/web-platform/tests/trusted-types/Range-createContextualFragment.tentative.html15
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedType-AttributeNodes.tentative.html92
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-no-name.tentative.html16
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-wildcard.tentative.html12
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicy-createXXX.tentative.html110
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-blocking.html48
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-constants.tentative.html43
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-createXYZTests.tentative.html241
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.tentative.html15
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html19
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html19
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.tentative.html13
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests.tentative.html27
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-nameTests.tentative.html40
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-unenforced.tentative.html16
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-defaultPolicy.tentative.html24
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getAttributeType-namespace.tentative.html62
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html108
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html84
-rw-r--r--testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-metadata.tentative.html154
-rw-r--r--testing/web-platform/tests/trusted-types/Window-TrustedTypes.tentative.html17
-rw-r--r--testing/web-platform/tests/trusted-types/WorkerGlobalScope-eval.html42
-rw-r--r--testing/web-platform/tests/trusted-types/WorkerGlobalScope-importScripts.html42
-rw-r--r--testing/web-platform/tests/trusted-types/block-Document-execCommand.tentative.html44
-rw-r--r--testing/web-platform/tests/trusted-types/block-Node-multiple-arguments.tentative.html91
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMParser-parseFromString.tentative.html48
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.tentative.html68
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Document-write.tentative.html81
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-insertAdjacentHTML.tentative.html147
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-outerHTML.tentative.html78
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html112
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html60
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-HTMLElement-generic.tentative.html78
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-Range-createContextualFragment.tentative.html53
-rw-r--r--testing/web-platform/tests/trusted-types/block-string-assignment-to-attribute-via-attribute-node.tentative.html42
-rw-r--r--testing/web-platform/tests/trusted-types/block-text-node-insertion-into-script-element.tentative.html238
-rw-r--r--testing/web-platform/tests/trusted-types/csp-block-eval.tentative.html31
-rw-r--r--testing/web-platform/tests/trusted-types/default-policy-callback-arguments.tentative.html50
-rw-r--r--testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html108
-rw-r--r--testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/default-policy.tentative.html108
-rw-r--r--testing/web-platform/tests/trusted-types/default-policy.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html56
-rw-r--r--testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html52
-rw-r--r--testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/eval-csp-no-tt.tentative.html36
-rw-r--r--testing/web-platform/tests/trusted-types/eval-csp-tt-default-policy.tentative.html37
-rw-r--r--testing/web-platform/tests/trusted-types/eval-csp-tt-no-default-policy.tentative.html36
-rw-r--r--testing/web-platform/tests/trusted-types/eval-function-constructor.tentative.html41
-rw-r--r--testing/web-platform/tests/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html37
-rw-r--r--testing/web-platform/tests/trusted-types/eval-no-csp-no-tt.tentative.html36
-rw-r--r--testing/web-platform/tests/trusted-types/eval-with-permissive-csp.tentative.html52
-rw-r--r--testing/web-platform/tests/trusted-types/idlharness.tentative.window.js16
-rw-r--r--testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html44
-rw-r--r--testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/no-require-trusted-types-for.tentative.html44
-rw-r--r--testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html71
-rw-r--r--testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/require-trusted-types-for.tentative.html78
-rw-r--r--testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.html18
-rw-r--r--testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.js2
-rw-r--r--testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js37
-rw-r--r--testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js84
-rw-r--r--testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/support/frame-without-trusted-types.html6
-rw-r--r--testing/web-platform/tests/trusted-types/support/helper.sub.js166
-rw-r--r--testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html53
-rw-r--r--testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/support/navigation-support.html51
-rw-r--r--testing/web-platform/tests/trusted-types/support/navigation-support.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/support/set-inner-html.js3
-rw-r--r--testing/web-platform/tests/trusted-types/support/worker.js1
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-createHTMLDocument.tentative.html71
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html20
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list.tentative.html23
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-without-enforcement.tentative.html30
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-duplicate-names.tentative.html25
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html113
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html.headers3
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html107
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html.headers4
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html102
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html.headers4
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-event-handlers.tentative.html53
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-from-literal.tentative.html118
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-navigation.tentative.html100
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html86
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html22
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html.sub.headers6
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html279
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html.headers6
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-source-file-path.tentative.html74
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-svg-script.tentative.html144
-rw-r--r--testing/web-platform/tests/trusted-types/trusted-types-tojson.tentative.html24
-rw-r--r--testing/web-platform/tests/trusted-types/tt-block-eval.tentative.html19
-rw-r--r--testing/web-platform/tests/trusted-types/worker-constructor.https.html86
116 files changed, 6006 insertions, 0 deletions
diff --git a/testing/web-platform/tests/trusted-types/DOMParser-parseFromString-regression.tentative.html b/testing/web-platform/tests/trusted-types/DOMParser-parseFromString-regression.tentative.html
new file mode 100644
index 0000000000..941d1750b4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/DOMParser-parseFromString-regression.tentative.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta http-equiv="Content-Security-Policy" content="blabla">
+<body>
+<div id="target"></div>
+<div id="probe"></div>
+<script>
+test(t => {
+ // Regression test for crbug.com/1030830. (Should work in any browser, though.)
+ //
+ // The top-level doc has a CSP that doesn't do anything interesting. We'll
+ // parse a doc and create an iframe with an embedded CSP, and will ensure that
+ // the CSP applies to the frame, but not the top-level doc.
+ const target = document.getElementById("target");
+ const probe = document.getElementById("probe");
+ probe.innerHTML = "probe";
+
+ const doc = new DOMParser().parseFromString(`
+ <body><div id="probe"></div></body>"`, "text/html");
+ probe.innerHTML = "probe";
+
+ const frame = document.createElement("iframe");
+ frame.src = `data:text/html;${encodeURI(doc.documentElement.outerHTML)}`;
+ frame.id = "frame";
+ target.appendChild(frame);
+ const frame_probe = document.getElementById("frame").contentDocument.getElementById("probe");
+ probe.innerHTML = "probe";
+ assert_throws_js(TypeError, _ => { frame_probe.innnerHTML = "probe" });
+}, "Regression test for TT changes to parseFromString.");
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/DOMParser-parseFromString.tentative.html b/testing/web-platform/tests/trusted-types/DOMParser-parseFromString.tentative.html
new file mode 100644
index 0000000000..2dfc37686b
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/DOMParser-parseFromString.tentative.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ let parser = new DOMParser();
+ let doc = parser.parseFromString(html, "text/html");
+ assert_equals(doc.body.innerText, RESULTS.HTML);
+ }, "document.innerText assigned via policy (successful HTML transformation).");
+
+ test(t => {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(null, "text/html");
+ assert_equals(doc.body.innerText, "null");
+ }, "document.innerText = null.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.tentative.html b/testing/web-platform/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.tentative.html
new file mode 100644
index 0000000000..2ad47555a9
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.tentative.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+<body>
+<script>
+ async_test(t => {
+ window.timeoutTrustedTest = t;
+ let policy = createScript_policy(window, 'timeout');
+ let script = policy.createScript("window.timeoutTrustedTest.done();");
+ setTimeout(script);
+ }, "window.setTimeout assigned via policy (successful Script transformation).");
+
+ async_test(t => {
+ window.intervalTrustedTest = t;
+ let policy = createScript_policy(window, 'script');
+ let script = policy.createScript("window.intervalTrustedTest.done();");
+ setInterval(script);
+ }, "window.setInterval assigned via policy (successful Script transformation).");
+
+ trustedTypes.createPolicy("default", {createScript: s => "window." + s + ".done()"});
+
+ async_test(t => {
+ window.timeoutStringTest = t;
+ let script = "timeoutStringTest";
+ setTimeout(script);
+ }, "window.setTimeout assigned via default policy (successful Script transformation).");
+
+ async_test(t => {
+ window.intervalStringTest = t;
+ let script = "intervalStringTest";
+ setInterval(script);
+ }, "window.setInterval assigned via default policy (successful Script transformation).");
+
+ async_test(t => {
+ window.timeoutFunctionTest = t;
+ let script = () => window.timeoutFunctionTest.done();
+ setTimeout(script);
+ }, "window.setTimeout assigned with a function handler shouldn't go through default policy.");
+
+ async_test(t => {
+ window.intervalFunctionTest = t;
+ let script = () => window.intervalFunctionTest.done();
+ setInterval(script);
+ }, "window.setInterval assigned with a function handler shouldn't go through default policy.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Document-execCommand.tentative.html b/testing/web-platform/tests/trusted-types/Document-execCommand.tentative.html
new file mode 100644
index 0000000000..7619133655
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Document-execCommand.tentative.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Daniel Vogelheim" href="mailto:vogelheim@chromium.org"></link>
+<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/"></link>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+ // Test that execCommand continues to work if Trusted Types is not enabled.
+ const commands = [ "insertHTML", "paste" ];
+ for (const command of commands) {
+ test(t => {
+ document.execCommand(command, false, "<em>Hello World</em>");
+ }, `Document.execCommand("${command}") works as usual.`);
+ }
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Document-write.tentative.html b/testing/web-platform/tests/trusted-types/Document-write.tentative.html
new file mode 100644
index 0000000000..87e9e72469
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Document-write.tentative.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ // TrustedHTML assignments do not throw.
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ document.write(html);
+ assert_true(document.body.innerText.indexOf(RESULTS.HTML) !== -1);
+ }, "document.write with html assigned via policy (successful transformation).");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Element-insertAdjacentHTML.tentative.html b/testing/web-platform/tests/trusted-types/Element-insertAdjacentHTML.tentative.html
new file mode 100644
index 0000000000..6a9329b3fb
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Element-insertAdjacentHTML.tentative.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<div id="container"></div>
+<script>
+ var container = document.querySelector('#container');
+
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ let before = 'before';
+ let after = 'after';
+ let htmlBefore = p.createHTML(before);
+ let htmlAfter = p.createHTML(after);
+
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ d.insertAdjacentHTML('beforebegin', html);
+ assert_equals(d.previousSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.previousSibling.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('afterbegin', htmlBefore);
+ d.insertAdjacentHTML('beforeend', htmlAfter);
+ assert_equals(d.innerHTML, before + after);
+
+ d.insertAdjacentHTML('afterend', html);
+ assert_equals(d.nextSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.nextSibling.data, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "insertAdjacentHTML with html assigned via policy (successful HTML transformation).");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Element-insertAdjacentText.tentative.html b/testing/web-platform/tests/trusted-types/Element-insertAdjacentText.tentative.html
new file mode 100644
index 0000000000..f6221362c1
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Element-insertAdjacentText.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<div id="container"></div>
+<script>
+ var container = document.querySelector('#container');
+
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ let before = 'before';
+ let after = 'after';
+ let htmlBefore = p.createHTML(before);
+ let htmlAfter = p.createHTML(after);
+
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ d.insertAdjacentHTML('beforebegin', html);
+ assert_equals(d.previousSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.previousSibling.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('afterbegin', htmlBefore);
+ d.insertAdjacentHTML('beforeend', htmlAfter);
+ assert_equals(d.innerHTML, before + after);
+
+ d.insertAdjacentHTML('afterend', html);
+ assert_equals(d.nextSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.nextSibling.data, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "insertAdjacentHTML with html assigned via policy (successful HTML transformation).");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/Element-outerHTML.tentative.html b/testing/web-platform/tests/trusted-types/Element-outerHTML.tentative.html
new file mode 100644
index 0000000000..c8daddfe99
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Element-outerHTML.tentative.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<div id="container"></div>
+<script>
+ var container = document.querySelector('#container');
+
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+
+ var d = document.createElement('div');
+ document.querySelector('#container').appendChild(d);
+ d.outerHTML = html;
+ assert_equals(container.innerText, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "outerHTML with html assigned via policy (successful HTML transformation).");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Element-setAttribute.tentative.html b/testing/web-platform/tests/trusted-types/Element-setAttribute.tentative.html
new file mode 100644
index 0000000000..cd6617915b
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Element-setAttribute.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<script>
+ // TrustedScriptURL Assignments
+ let scriptTestCases = [
+ [ 'embed', 'src' ],
+ [ 'script', 'src' ]
+ ];
+
+ scriptTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_script_url_explicit_set(window, c, t, c[0], c[1], RESULTS.SCRIPTURL);
+ }, c[0] + "." + c[1] + " assigned via policy (successful ScriptURL transformation)");
+ });
+
+ // TrustedHTML Assignments
+ let HTMLTestCases = [
+ [ 'iframe', 'srcdoc' ]
+ ];
+
+ HTMLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_html_explicit_set(window, c, t, c[0], c[1], RESULTS.HTML);
+ }, c[0] + "." + c[1] + " assigned via policy (successful HTML transformation)");
+ });
+
+ // Other attributes can be assigned with TrustedTypes or strings or null values
+ test(t => {
+ assert_element_accepts_trusted_script_url_explicit_set(window, 'scriptsrc1', t, 'script', 'src', RESULTS.SCRIPTURL);
+ }, "script.src assigned via policy (successful script transformation)");
+
+ test(t => {
+ assert_element_accepts_non_trusted_type_explicit_set('a', 'rel', 'A string', 'A string');
+ }, "a.rel accepts strings");
+
+ test(t => {
+ assert_element_accepts_non_trusted_type_explicit_set('a', 'rel', null, 'null');
+ }, "a.rel accepts null");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/Element-setAttributeNS.tentative.html b/testing/web-platform/tests/trusted-types/Element-setAttributeNS.tentative.html
new file mode 100644
index 0000000000..67e8236feb
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Element-setAttributeNS.tentative.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<script>
+ test(t => {
+ assert_element_accepts_trusted_html_set_ns(window, '0', t, 'a', 'b', RESULTS.HTML);
+ }, "Element.setAttributeNS assigned via policy (successful HTML transformation)");
+
+ test(t => {
+ assert_element_accepts_trusted_script_set_ns(window, '1', t, 'a', 'b', RESULTS.SCRIPT);
+ }, "Element.setAttributeNS assigned via policy (successful Script transformation)");
+
+ test(t => {
+ assert_element_accepts_trusted_script_url_set_ns(window, '2', t, 'a', 'b', RESULTS.SCRIPTURL);
+ }, "Element.setAttributeNS assigned via policy (successful ScriptURL transformation)");
+
+// TODO: Is there any non-URL, namespaced accessor left?
+/*
+ test(t => {
+ let p = createURL_policy(window, '5');
+ let url = p.createURL(INPUTS.URL);
+
+ let elem = document.createElementNS("http://www.w3.org/2000/svg", "image");
+ elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", url);
+ let attr_node = elem.getAttributeNodeNS("http://www.w3.org/1999/xlink", "href");
+ assert_equals(attr_node.value + "", RESULTS.URL);
+ }, "Element.setAttributeNS accepts a URL on <svg:image xlink:href/>");
+*/
+
+</script>
diff --git a/testing/web-platform/tests/trusted-types/GlobalEventHandlers-onclick.tentative.html b/testing/web-platform/tests/trusted-types/GlobalEventHandlers-onclick.tentative.html
new file mode 100644
index 0000000000..0fdde778cc
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/GlobalEventHandlers-onclick.tentative.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+<body>
+<div id="container"></div>
+<script>
+var container = document.querySelector('#container');
+const policy = createScript_policy(window, 'onclick');
+const policy_html = createHTML_policy(window, 'onclick-html');
+
+// Trusted Type assignments do not throw.
+async_test(t => {
+ window.onclickDone1 = t.step_func_done();
+ let script = policy.createScript("window.onclickDone1();");
+ let el = document.createElement('a');
+ el.setAttribute('onclick', script);
+ container.appendChild(el);
+ el.click();
+}, "a.setAttribte('onclick') sets a trusted script.");
+
+// Unsuitable TrustedType assignments do throw.
+async_test(t => {
+ window.onclickFail1 = t.unreached_func();
+ let script = policy_html.createHTML("window.onclickFail1();");
+ let el = document.createElement('a');
+ try {
+ el.setAttribute('onclick', script);
+ container.appendChild(el);
+ el.click();
+ } catch (e) {
+ t.done();
+ }
+ assert_unreached();
+}, "a.setAttribute('onclick') sets an unsuitable trusted type.");
+
+// So do plain test assignments.
+async_test(t => {
+ window.onclickFail2 = t.unreached_func();
+ let el = document.createElement('a');
+ try {
+ el.setAttribute("onclick", "window.onclickFail2();");
+ container.appendChild(el);
+ el.click();
+ } catch (e) {
+ t.done();
+ }
+ assert_unreached();
+}, "a.setAttribute('click') sets a test string.");
+/*
+// Trusted Type assignments via property access does not throw.
+async_test(t => {
+ window.onclickDone2 = t.step_func_done();
+ let script = policy.createScript("window.onclickDone2();");
+ let el = document.createElement('a');
+ el.onclick = script;
+ container.appendChild(el);
+ el.click();
+}, "a.onclick assigned via policy (successful Script transformation).");
+
+// Unsuitable TrustedType assignments do throw.
+async_test(t => {
+ window.onclickFail3 = t.unreached_func();
+ let script = policy_html.createHTML("window.onclickFail3();");
+ let el = document.createElement('a');
+ try {
+ el.onclick = script;
+ container.appendChild(el);
+ el.click();
+ } catch (e) {
+ t.done();
+ }
+ assert_unreached();
+}, "a.onclick assigned via an unsuitable policy.");
+
+// So do plain test assignments.
+async_test(t => {
+ window.onclickFail4 = t.unreached_func();
+ let el = document.createElement('a');
+ try {
+ el.onclick = window.onclickFail4();
+ container.appendChild(el);
+ el.click();
+ } catch (e) {
+ t.done();
+ }
+ assert_unreached();
+}, "a.onclick assigned a test string.");
+*/
+</script>
diff --git a/testing/web-platform/tests/trusted-types/HTMLElement-generic.tentative.html b/testing/web-platform/tests/trusted-types/HTMLElement-generic.tentative.html
new file mode 100644
index 0000000000..8e54fa9c57
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/HTMLElement-generic.tentative.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<script>
+const policy = trustedTypes.createPolicy("testpolicy", {
+ createScript: s => s,
+ createHTML: s => s,
+ createScriptURL: s => s,
+});
+
+function getTrusted(element, attr) {
+ const type = trustedTypes.getPropertyType(element, attr);
+ if (type == "TrustedScript") {
+ return policy.createScript("2+2");
+ } else if (type == "TrustedScriptURL") {
+ return policy.createScript("https://example.test/");
+ } else if (type == "TrustedHTML") {
+ return policy.createHTML("<b>hello</b>");
+ } else {
+ return "a simple string";
+ }
+}
+
+// This test will run a simple, TT-relevant assignment, in a number of
+// circumstances. We've had issues where subtle difference in DOM behaviour -
+// for example a connected element or a non-connected element - produce
+// different results, and no test catching it because the tests were written
+// to do it one particular way. So this test does one thing, but in all the
+// different ways we can think of.
+//
+// - With TT disabled or enabled,
+// - with any of the trusted types,
+// - with a string or a TT value,
+// - with a element that's connected to the DOM (or not).
+//
+// Run the set of tests, assuming that is_tt_enabled reflects whether Trusted
+// Types is currently enabled (& enforced) or not.
+function runTests(is_tt_enabled) {
+ for (const [element, attr] of [
+ [ 'embed', 'src' ],
+ [ 'script', 'src' ],
+ [ 'div', 'innerHTML' ],
+ [ 'iframe', 'srcdoc' ],
+ [ 'script', 'text' ],
+ [ 'script', 'innerText' ],
+ [ 'script', 'textContent' ],
+ ]) {
+ const trusted = getTrusted(element, attr);
+ for (const value of [trusted, trusted.toString()]) {
+ for (const connected of [true, false]) {
+
+ const expect_exception = is_tt_enabled &&
+ value.constructor.name != trustedTypes.getPropertyType(element, attr);
+ test(t => {
+ const elem = document.createElement(element);
+ if (connected) document.body.appendChild(elem);
+ if (expect_exception) {
+ assert_throws_js(TypeError, _ => { elem[attr] = value; });
+ } else {
+ elem[attr] = value;
+ }
+ }, `${is_tt_enabled ? "TT enabled" : "TT disabled"}: ${element}.${attr} = ${value.constructor.name} on a ${connected ? "connected" : "non-connected"} element.`);
+ }
+ }
+ }
+}
+
+// Run the tests without TT first.
+runTests(false);
+
+// Now run the tests a second time, with TT enabled. To accomplish this, insert
+// a suitable <meta> element.
+const meta = document.createElement("meta");
+meta.setAttribute("http-equiv", "Content-Security-Policy");
+meta.setAttribute("content", "require-trusted-types-for 'script';");
+document.head.appendChild(meta);
+runTests(true);
+</script>
diff --git a/testing/web-platform/tests/trusted-types/HTMLScriptElement-in-xhtml-document.tentative.https.xhtml b/testing/web-platform/tests/trusted-types/HTMLScriptElement-in-xhtml-document.tentative.https.xhtml
new file mode 100644
index 0000000000..6cf49f922a
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/HTMLScriptElement-in-xhtml-document.tentative.https.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"/>
+</head>
+<body>
+<script>
+ // This this a regresion test that verifies that in-tree script element in
+ // an xhtml document still works correctly. The test itself doesn't do much.
+ test(t => {
+ t.done();
+ }, "Test whether a script element still executes for XHTML documents.");
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/trusted-types/HTMLScriptElement-internal-slot.tentative.html b/testing/web-platform/tests/trusted-types/HTMLScriptElement-internal-slot.tentative.html
new file mode 100644
index 0000000000..3a4b905f46
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/HTMLScriptElement-internal-slot.tentative.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+ promise_test(t => {
+ // Setup: We create an <iframe> and trigger loading the document. We use
+ // WPTserve's ?pipe functionality to make sure it gets delivered in chunks
+ // and that parsing will be deferred.
+ var frame = document.createElement("iframe");
+ document.body.appendChild(frame);
+ frame.src = "support/HTMLScriptElement-internal-slot-support.html?pipe=trickle(200:d1)";
+
+ // This function tries to find the first <script> element in our iframe and
+ // manipulated it with DOM APIs (appendChild + createTextNode). If it
+ // doesn't find the script element then it'll just enqueue itself again
+ // in 100ms.
+ var manipulator = _ => {
+ let script = frame.contentDocument.getElementsByTagName("script")[0];
+ if (script) {
+ script.appendChild(frame.contentDocument.createTextNode("/*byapi*/"));
+ } else {
+ t.step_timeout(manipulator, 100);
+ }
+ }
+ manipulator();
+
+ // Now we'll wait for the postMessages to arrive. We expect the iframe's
+ // first message to be blocked by Trusted Types, since the manipulator
+ // above should have manipulated it (while loading). The second one should
+ // pass.
+ return new Promise((resolve, reject) => {
+ window.addEventListener("message", e => {
+ if (e.data.includes("first")) {
+ reject("First message should have been blocked: " + e.data);
+ } else if (e.data.includes("second")) {
+ resolve();
+ } else {
+ reject("Unknown message: " + e.data);
+ }
+ });
+ });
+ }, "Test TT application when manipulating <script> elements during loading.");
+
+ // Test that a script set via textContent or innerTest actually executes
+ // (and not only doesn't throw an exception, which it wouldn't do due to the
+ // "internal slot" mechanism).
+ const policy = trustedTypes.createPolicy("testpolicy", {
+ createScript: x => x, createScriptURL: x => x});
+ promise_test(t => {
+ const s = document.createElement("script");
+ document.body.appendChild(s);
+ s.textContent = policy.createScript("window.postMessage('hello');");
+ return new Promise(resolve => {
+ window.addEventListener("message", e => {
+ if (e.data == "hello") resolve();
+ });
+ });
+ }, "Script set via .textContent executes on a connected HTMLScriptElement.");
+ promise_test(t => {
+ const s = document.createElement("script");
+ s.textContent = policy.createScript("window.postMessage('world');");
+ document.body.appendChild(s);
+ return new Promise(resolve => {
+ window.addEventListener("message", e => {
+ if (e.data == "world") resolve();
+ });
+ });
+ }, "Script set via .textContent executes on an unconnected HTMLScriptElement.");
+ promise_test(t => {
+ const s = document.createElement("script");
+ document.body.appendChild(s);
+ s.innerText = policy.createScript("window.postMessage('hello');");
+ return new Promise(resolve => {
+ window.addEventListener("message", e => {
+ if (e.data == "hello") resolve();
+ });
+ });
+ }, "Script set via .innerText executes on a connected HTMLScriptElement.");
+ promise_test(t => {
+ const s = document.createElement("script");
+ s.innerText= policy.createScript("window.postMessage('world');");
+ document.body.appendChild(s);
+ return new Promise(resolve => {
+ window.addEventListener("message", e => {
+ if (e.data == "world") resolve();
+ });
+ });
+ }, "Script set via .innerText executes on an unconnected HTMLScriptElement.");
+
+ // Test that interactions between the script content, the .src attribute, and
+ // exceptions still work correctly with TT and the "internal slot" thingy.
+ promise_test(t => {
+ const s = document.createElement("script");
+ s.textContent = policy.createScript("window.postMessage('script body');");
+ try {
+ s.src = "support/HTMLScriptElement-internal-slot-support.js";
+ } catch (e) {}
+ document.body.appendChild(s);
+ return new Promise((resolve, reject) => {
+ window.addEventListener("message", e => {
+ // .src was set with plain string => should not have been accepted.
+ if (e.data == "script body") resolve();
+ if (e.data == "script url") reject();
+ });
+ });
+ }, "Setting .src to a plain string should throw an exception and not modify the script state, on an unconnected script element.");
+
+ promise_test(t => {
+ const s = document.createElement("script");
+ s.textContent = policy.createScript("window.postMessage('script body');");
+ s.src = policy.createScriptURL("support/HTMLScriptElement-internal-slot-support.js");
+ document.body.appendChild(s);
+ return new Promise((resolve, reject) => {
+ window.addEventListener("message", e => {
+ // .src was set with a TrustedScriptURL => the .src should get executed.
+ if (e.data == "script body") reject();
+ if (e.data == "script url") resolve();
+ });
+ });
+ }, "Setting .src to a TrustedScriptURL should work and should execute the referenced script instead of the script body, on an unconnected script element.");
+
+ promise_test(t => {
+ const s = document.createElement("script");
+ document.body.appendChild(s);
+ s.textContent = policy.createScript("window.postMessage('script body');");
+ try {
+ s.src = "support/HTMLScriptElement-internal-slot-support.js";
+ } catch (e) {}
+ return new Promise((resolve, reject) => {
+ window.addEventListener("message", e => {
+ // .src was set with plain string => should not have been accepted.
+ if (e.data == "script body") resolve();
+ if (e.data == "script url") reject();
+ });
+ });
+ }, "Setting .src to a plain string should throw an exception and not modify the script state, on a connected script element.");
+
+ promise_test(t => {
+ const s = document.createElement("script");
+ s.textContent = policy.createScript("window.postMessage('script body');");
+ s.src = policy.createScriptURL("support/HTMLScriptElement-internal-slot-support.js");
+ document.body.appendChild(s);
+ return new Promise((resolve, reject) => {
+ window.addEventListener("message", e => {
+ // .src was set with a TrustedScriptURL => the .src should get executed.
+ if (e.data == "script body") reject();
+ if (e.data == "script url") resolve();
+ });
+ });
+ }, "Setting .src to a TrustedScriptURL should work and should execute the referenced script instead of the script body, on a onnected script element.");
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/META.yml b/testing/web-platform/tests/trusted-types/META.yml
new file mode 100644
index 0000000000..04061ac0f6
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/META.yml
@@ -0,0 +1,3 @@
+spec: https://w3c.github.io/trusted-types/dist/spec/
+suggested_reviewers:
+ - mikewest
diff --git a/testing/web-platform/tests/trusted-types/Node-multiple-arguments.tentative.html b/testing/web-platform/tests/trusted-types/Node-multiple-arguments.tentative.html
new file mode 100644
index 0000000000..64b04656d3
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Node-multiple-arguments.tentative.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<div id="container"></div>
+<script>
+ 'use strict';
+ const container = document.querySelector("#container");
+ const policy = window.trustedTypes.createPolicy("policy", {
+ createScript: t => t,
+ });
+ function stringify(arg) {
+ return "textContent" in Object.getPrototypeOf(arg) ? arg.textContent : arg.toString()
+ }
+
+ // This test case mirrors the block-Node-multiple-arguments case except
+ // that, because Trusted Types is not enabled, no exceptions should be
+ // thrown anywhere.
+ const targets = ["div", "script"];
+ const all_args = [
+ [ policy.createScript("'createScript';") ],
+ [ policy.createScript("'createScript #1';"), policy.createScript("'#2;'") ],
+ [ "'plain text';" ],
+ [ "'plain text #1';", "'plain text #2';" ],
+ [ document.createTextNode("'node';") ],
+ [ document.createTextNode("'node #1';"),
+ document.createTextNode("'node #2';") ],
+ [ "'mixed';", document.createTextNode("'node';") ],
+ [ "'mixed';", policy.createScript("'script';") ],
+ [ document.createTextNode("'node';"),
+ policy.createScript("'script';") ],
+ ];
+
+ for (const target of targets) {
+ for (const args of all_args) {
+
+ for (const setter of [container.replaceWith, container.after, container.before]) {
+ test(t => {
+ var outer = document.createElement(target);
+ container.appendChild(outer);
+ var inner = document.createElement("p");
+ outer.appendChild(inner);
+ setter.apply(inner, args);
+ assert_equals(outer.textContent, args.map(stringify).join(""));
+
+ }, `${setter.name}(${args.toString()}) on <${target}> should pass`);
+ }
+
+ for (const setter of [container.append, container.prepend]) {
+ test(t => {
+ let outer = document.createElement(target);
+ container.appendChild(outer);
+ setter.apply(outer, args);
+ assert_equals(outer.textContent, args.map(stringify).join(""));
+ }, `${setter.name}(${args.toString()}) on <${target}> should pass`);
+ }
+
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/Range-createContextualFragment.tentative.html b/testing/web-platform/tests/trusted-types/Range-createContextualFragment.tentative.html
new file mode 100644
index 0000000000..3a880a5377
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Range-createContextualFragment.tentative.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ var result = range.createContextualFragment(html);
+ assert_equals(result.textContent, RESULTS.HTML);
+ }, "range.createContextualFragment assigned via policy (successful HTML transformation).");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedType-AttributeNodes.tentative.html b/testing/web-platform/tests/trusted-types/TrustedType-AttributeNodes.tentative.html
new file mode 100644
index 0000000000..6b00665700
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedType-AttributeNodes.tentative.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ // This is a set of tests that try to make sure various ways of setting
+ // attributes (directly; via an attribute node; etc.) are all being treated
+ // identically. For background, se::
+ // https://github.com/w3c/webappsec-trusted-types/issues/47
+
+ const elems = ["div", "script", "embed", "iframe"];
+ const attrs = ["src", "srcdoc", "onclick", "bla"];
+
+ const policy_callback = s => ("" + s + " [policy]");
+ const policy = trustedTypes.createPolicy("policy", {
+ "createHTML": policy_callback,
+ "createScript": policy_callback,
+ "createScriptURL": policy_callback,
+ });
+
+ // Returns either the string-ified result value of fn, or an exception type.
+ function try_get(fn) {
+ try {
+ return "" + fn();
+ } catch(e) {
+ return "" + e.name;
+ }
+ }
+
+ // Returns a 'trusted' version of value, if element.attribute requires it.
+ function trusted(element, attribute, value) {
+ switch (trustedTypes.getAttributeType(element, attribute)) {
+ case 'TrustedHTML': value = policy.createHTML(value); break;
+ case 'TrustedScript': value = policy.createScript(value); break;
+ case 'TrustedScriptURL': value = policy.createScriptURL(value); break;
+ }
+ return value;
+ }
+
+ for (elem of elems) {
+ for (attr of attrs) {
+ const reference = try_get(_ => {
+ const e = document.createElement(elem);
+ e.setAttribute(attr, "hello");
+ return e.getAttribute(attr);
+ });
+
+ // Event handlers (like "onclick") apply to all elements, so we don't
+ // really have 'harmless' element we can attach them to. Hence this test
+ // case doesn't apply.
+ if (attr != "onclick") {
+ test(t => {
+ const harmless = document.createElement("div");
+ harmless.setAttribute(attr, "hello");
+ const node = harmless.getAttributeNode(attr);
+ harmless.removeAttributeNode(node);
+
+ const actual = try_get(_ => {
+ const e = document.createElement(elem);
+ e.setAttributeNode(node);
+ return e.getAttribute(attr);
+ });
+ assert_equals(actual, reference);
+ }, `Set attribute via attribute node on ${elem}.${attr}.`);
+ }
+
+ test(t => {
+ const e = document.createElement(elem);
+ e.setAttribute(attr, trusted(elem, attr, "123"));
+ const actual = try_get(_ => {
+ e.getAttributeNode(attr).value = "hello";
+ return e.getAttribute(attr);
+ });
+ assert_equals(actual, reference);
+ }, `Set attribute via attributenode.value on ${elem}.${attr}.`);
+
+ test(t => {
+ const e = document.createElement(elem);
+ const attrnode = document.createAttribute(attr);
+ attrnode.value = "hello";
+ const actual = try_get(_ => {
+ e.attributes.setNamedItem(attrnode);
+ return e.getAttribute(attr);
+ });
+ assert_equals(actual, reference);
+ }, `Set attribute via NamedNodeMap.setNamedItem on ${elem}.${attr}.`);
+ }
+ }
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-no-name.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-no-name.tentative.html
new file mode 100644
index 0000000000..b1c7f51ddb
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-no-name.tentative.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="trusted-types">
+<body>
+<script>
+ // No name given test
+ test(t => {
+ assert_throws_js(TypeError,
+ () => window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } ),
+ "createPolicy with an empty trusted-types CSP directive");
+ }, "No name list given - policy creation fails.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-wildcard.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-wildcard.tentative.html
new file mode 100644
index 0000000000..cdc683dad3
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-CSP-wildcard.tentative.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<body>
+<script>
+ test(t => {
+ let policy = window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ assert_equals(policy.name, 'SomeName');
+ }, "CSP supports wildcards.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicy-createXXX.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-createXXX.tentative.html
new file mode 100644
index 0000000000..112d1ae636
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicy-createXXX.tentative.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<body>
+<script>
+ test(t => {
+ const p1 = trustedTypes.createPolicy("policyHTMLAndScript", {
+ createHTML: s => s,
+ createScript: s => s
+ });
+ assert_throws_js(TypeError, _ => { p1.createScriptURL("foo"); });
+
+ const p2 = trustedTypes.createPolicy("policyURLAndScriptURL", {
+ createScriptURL: s => s
+ });
+ assert_throws_js(TypeError, _ => { p2.createHTML("foo"); });
+ assert_throws_js(TypeError, _ => { p2.createScript("foo"); });
+ }, "calling undefined callbacks throws");
+
+ test(t => {
+ const noopPolicy = {
+ createHTML: (s) => s,
+ createScriptURL: (s) => s,
+ createScript: (s) => s,
+ };
+ policy = trustedTypes.createPolicy(Math.random(), noopPolicy, true);
+ let el = document.createElement("div");
+
+ el.title = policy.createHTML(INPUTS.SCRIPTURL);
+ assert_equals(el.title, INPUTS.SCRIPTURL);
+ }, "Attributes without type constraints will work as before.");
+
+ test(t => {
+ const policy = trustedTypes.createPolicy("nullpolicy", null);
+ assert_throws_js(TypeError, _ => { policy.createScriptURL("foo"); });
+ assert_throws_js(TypeError, _ => { policy.createHTML("foo"); });
+ assert_throws_js(TypeError, _ => { policy.createScript("foo"); });
+ }, "trustedTypes.createPolicy(.., null) creates empty policy.");
+
+
+ // testCases contains a list of policy functions and expected results (when
+ // called with a given default argument). They also use various helper
+ // variables (declared just below) to test side effects or interactions of
+ // global vars/functions with policy callbacks.
+ let aGlobalVarForSideEffectTesting = "global";
+ var aGlobalObject = { "foo": "well," };
+ function aGlobalFunction(s) { return this.foo + " " + s; }
+ function anotherGlobalFunction(s) { return s + "#" + this.foo; }
+ var foo = "a global var named foo";
+
+ const stringTestCases = [
+ [ s => s, "whatever" ],
+ [ s => null, "" ],
+ [ s => "well, " + s, "well, whatever" ],
+ [ s => { throw new Error() }, Error ],
+ [ s => { aGlobalVarForSideEffectTesting = s; return s }, "whatever" ],
+ [ s => aGlobalVarForSideEffectTesting + s, "whateverwhatever" ],
+ [ aGlobalFunction.bind(aGlobalObject), "well, whatever" ],
+ [ s => aGlobalFunction(s), "a global var named foo whatever" ],
+ ];
+
+ const urlTestCases = [
+ [ s => s, INPUTS.SCRIPTURL ],
+ [ s => null, "" ],
+ [ s => s + "#duck", INPUTS.SCRIPTURL + "#duck" ],
+ [ s => { throw new Error() }, Error ],
+ [ s => s + "#" + aGlobalVarForSideEffectTesting,
+ INPUTS.SCRIPTURL + "#global" ],
+ [ anotherGlobalFunction.bind(aGlobalObject), INPUTS.SCRIPTURL + "#well," ],
+ [ s => anotherGlobalFunction(s),
+ INPUTS.SCRIPTURL + "#a global var named foo" ],
+ ];
+
+ function policyBuilder(trustedMethodName, trustedType, defaultArg) {
+ return function(name, fn) {
+ let options = {};
+ options[trustedMethodName] = fn;
+ let policy = window.trustedTypes.createPolicy(name, options);
+ let result = policy[trustedMethodName](defaultArg);
+ assert_true(result instanceof trustedType);
+ return result;
+ }
+ }
+
+ const testCases = [
+ [TrustedHTML, "createHTML", "whatever", stringTestCases],
+ [TrustedScript, "createScript", "whatever", stringTestCases],
+ [TrustedScriptURL, "createScriptURL", INPUTS.SCRIPTURL, urlTestCases],
+ ];
+
+ // Iterate over all trusted types, iterate over all test cases.
+ // For each, build the suitable policy and check the result.
+ for (let [trusted_class, trusted_method, default_arg, test_cases] of testCases) {
+ aGlobalVarForSideEffectTesting = "global";
+ let builder = policyBuilder(trusted_method, trusted_class, default_arg);
+ for (let [index, [policy_fn, value]] of test_cases.entries()) {
+ let subtest_name = "TestPolicy" + trusted_class.name + index;
+ test(t => {
+ if (typeof value == "object" || typeof value == "function") {
+ assert_throws_js(value, () => builder(subtest_name, policy_fn));
+ } else {
+ assert_equals("" + builder(subtest_name, policy_fn), value);
+ }
+ }, subtest_name + " (" + trusted_class.name + ": " +
+ policy_fn.toString() + ")");
+ }
+ }
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-blocking.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-blocking.html
new file mode 100644
index 0000000000..6ae71b6988
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-blocking.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types *">
+
+<body>
+<script>
+
+ test(t => {
+ event_listener = (e) => {
+ assert_equals(e.policyName, "default");
+ e.preventDefault(); // don't let this policy be created.
+ };
+ trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+ assert_throws_dom("NotAllowedError", () => trustedTypes.createPolicy("default", {}));
+ }, 'Block Trusted Type policy creation by event listener.');
+
+ test(t => {
+ let flag = false;
+ event_listener = (e) => {
+ assert_equals(e.policyName, "myPolicy");
+ flag = true;
+ };
+ trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+ trustedTypes.createPolicy("myPolicy", {});
+ assert_equals(flag, true);
+ }, 'Trusted Type policy creation.');
+
+ test(t => {
+ event_listener = (e) => {
+ if (e.policyName === "default")
+ e.preventDefault();
+ };
+ trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+ assert_throws_dom("NotAllowedError", () => trustedTypes.createPolicy("default", {}));
+ trustedTypes.createPolicy("newPolicy", {});
+ }, 'Block only default Trusted Type policy creation.');
+
+ test(t => {
+ event_listener = (e) => {
+ assert_unreached();
+ };
+ trustedTypes.createPolicy("test", {});
+ trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+ }, 'Policy creation called before addEventListener function will not reached the listener.');
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-constants.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-constants.tentative.html
new file mode 100644
index 0000000000..551084ca4b
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-constants.tentative.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<body>
+<script>
+ test(t => {
+ const empty = trustedTypes.emptyHTML;
+ assert_true(trustedTypes.isHTML(empty));
+ assert_equals(empty.toString(), "");
+ }, 'trustedTypes.emptyHTML returns the intended value.');
+
+ test(t => {
+ try { trustedTypes.emptyHTML = 'fake'; } catch { }
+ assert_true(trustedTypes.isHTML(trustedTypes.emptyHTML));
+ assert_equals(trustedTypes.emptyHTML.toString(), "");
+ }, 'trustedTypes.emptyHTML cannot be redefined.');
+
+ test(t => {
+ try { Object.defineProperty(TrustedTypes, 'emptyHTML', 'fake'); } catch { }
+ assert_true(trustedTypes.isHTML(trustedTypes.emptyHTML));
+ assert_equals(trustedTypes.emptyHTML.toString(), "");
+ }, 'trustedTypes.emptyHTML cannot be redefined via defineProperty.');
+
+ test(t => {
+ const empty = trustedTypes.emptyScript;
+ assert_true(trustedTypes.isScript(empty));
+ assert_equals(empty.toString(), "");
+ }, 'trustedTypes.emptyScript returns the intended value.');
+
+ test(t => {
+ try { trustedTypes.emptyScript = 'fake'; } catch { }
+ assert_true(trustedTypes.isScript(trustedTypes.emptyScript));
+ assert_equals(trustedTypes.emptyScript.toString(), "");
+ }, 'trustedTypes.emptyScript cannot be redefined.');
+
+ test(t => {
+ try { Object.defineProperty(TrustedTypes, 'emptyScript', 'fake'); } catch { }
+ assert_true(trustedTypes.isScript(trustedTypes.emptyScript));
+ assert_equals(trustedTypes.emptyScript.toString(), "");
+ }, 'trustedTypes.emptyScript cannot be redefined via defineProperty.');
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-createXYZTests.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-createXYZTests.tentative.html
new file mode 100644
index 0000000000..746d89fa3f
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-createXYZTests.tentative.html
@@ -0,0 +1,241 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ //HTML tests
+ function createHTMLTest(policyName, policy, expectedHTML, t) {
+ let p = window.trustedTypes.createPolicy(policyName, policy);
+ let html = p.createHTML('whatever');
+ assert_true(html instanceof TrustedHTML);
+ assert_true(trustedTypes.isHTML(html));
+ assert_equals(html + "", expectedHTML);
+ }
+
+ test(t => {
+ createHTMLTest('TestPolicyHTML1', { createHTML: s => s }, 'whatever', t);
+ }, "html = identity function");
+
+ test(t => {
+ createHTMLTest('TestPolicyHTML2', { createHTML: s => null }, "", t);
+ }, "html = null");
+
+ var HTMLstr = 'well, ';
+ test(t => {
+ createHTMLTest('TestPolicyHTML3', { createHTML: s => HTMLstr + s }, HTMLstr + 'whatever', t);
+ }, "html = string + global string");
+
+ var HTMLx = 'global';
+ test(t => {
+ createHTMLTest('TestPolicyHTML4', { createHTML: s => { HTMLx = s; return s; } }, 'whatever', t);
+ assert_equals(HTMLx, 'whatever');
+ }, "html = identity function, global string changed");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyHTML5', { createHTML: s => { throw new Error(); }});
+ assert_throws_js(Error, _ => {
+ p.createHTML('whatever');
+ });
+ }, "html = callback that throws");
+
+ var obj = {
+ "foo": "well,"
+ }
+
+ function getHTML(s) {
+ return this.foo + " " + s;
+ }
+
+ test(t => {
+ createHTMLTest('TestPolicyHTML6', { createHTML: getHTML.bind(obj) }, 'well, whatever', t);
+ }, "html = this bound to an object");
+
+ var foo = "well,";
+ test(t => {
+ createHTMLTest('TestPolicyHTML7', { createHTML: s => getHTML(s) }, 'well, whatever', t);
+ }, "html = this without bind");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyHTML8', null);
+ assert_throws_js(TypeError, _ => {
+ p.createHTML('whatever');
+ });
+ }, "html - calling undefined callback throws");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyHTML9', { createHTML: createHTMLJS });
+ assert_throws_js(TypeError, _ => {
+ p.createScript(INPUTS.SCRIPT);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createScriptURL(INPUTS.SCRIPTURL);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createURL(INPUTS.URL);
+ });
+ }, "createHTML defined - calling undefined callbacks throws");
+
+ //Script tests
+ function createScriptTest(policyName, policy, expectedScript, t) {
+ let p = window.trustedTypes.createPolicy(policyName, policy);
+ let script = p.createScript('whatever');
+ assert_true(script instanceof TrustedScript);
+ assert_true(trustedTypes.isScript(script));
+ assert_equals(script + "", expectedScript);
+ }
+
+ test(t => {
+ createScriptTest('TestPolicyScript1', { createScript: s => s }, 'whatever', t);
+ }, "script = identity function");
+
+ test(t => {
+ createScriptTest('TestPolicyScript2', { createScript: s => null }, "", t);
+ }, "script = null");
+
+ var Scriptstr = 'well, ';
+ test(t => {
+ createScriptTest('TestPolicyScript3', { createScript: s => Scriptstr + s }, Scriptstr + 'whatever', t);
+ }, "script = string + global string");
+
+ var Scriptx = 'global';
+ test(t => {
+ createScriptTest('TestPolicyScript4', { createScript: s => { Scriptx = s; return s; } }, 'whatever', t);
+ assert_equals(Scriptx, 'whatever');
+ }, "script = identity function, global string changed");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScript5', {
+ createScript: s => { throw new Error(); }
+ });
+ assert_throws_js(Error, _ => {
+ p.createScript('whatever');
+ });
+ }, "script = callback that throws");
+
+ var obj = {
+ "foo": "well,"
+ }
+
+ function getScript(s) {
+ return this.foo + " " + s;
+ }
+
+ test(t => {
+ createScriptTest('TestPolicyScript6', { createScript: getScript.bind(obj) }, 'well, whatever', t);
+ }, "script = this bound to an object");
+
+ var foo = "well,";
+ test(t => {
+ createScriptTest('TestPolicyScript7', { createScript: s => getScript(s) }, 'well, whatever', t);
+ }, "script = this without bind");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScript8', null);
+ assert_throws_js(TypeError, _ => {
+ p.createScript('whatever');
+ });
+ }, "script - calling undefined callback throws");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScript9', { createScript: createScriptJS });
+ assert_throws_js(TypeError, _ => {
+ p.createHTML(INPUTS.HTML);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createScriptURL(INPUTS.SCRIPTURL);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createURL(INPUTS.URL);
+ });
+ }, "createScript defined - calling undefined callbacks throws");
+
+
+ //ScriptURL tests
+ function createScriptURLTest(policyName, policy, expectedScriptURL, t) {
+ let p = window.trustedTypes.createPolicy(policyName, policy);
+ let scriptUrl = p.createScriptURL(INPUTS.SCRIPTURL);
+ assert_true(scriptUrl instanceof TrustedScriptURL);
+ assert_true(trustedTypes.isScriptURL(scriptUrl));
+ assert_equals(scriptUrl + "", expectedScriptURL);
+ }
+
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL1', { createScriptURL: s => s }, INPUTS.SCRIPTURL, t);
+ }, "script_url = identity function");
+
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL2', { createScriptURL: s => null }, "", t);
+ }, "script_url = null");
+
+ var scriptURLstr = '#duck';
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL3', { createScriptURL: s => s + scriptURLstr }, INPUTS.SCRIPTURL + scriptURLstr, t);
+ }, "script_url = string + global string");
+
+ var scriptURLx = 'global';
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL4', { createScriptURL: s => { ScriptURLx = s; return s; } }, INPUTS.SCRIPTURL, t);
+ assert_equals(ScriptURLx, INPUTS.SCRIPTURL);
+ }, "script_url = identity function, global string changed");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScriptURL5', {
+ createScriptURL: s => { throw new Error(); }
+ });
+ assert_throws_js(Error, _ => {
+ p.createScriptURL(INPUTS.SCRIPTURL);
+ });
+ }, "script_url = callback that throws");
+
+ function getScriptURL(s) {
+ return s + this.baz;
+ }
+
+ var obj = {
+ "baz": "#duck"
+ }
+
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL6', { createScriptURL: getScriptURL.bind(obj) }, INPUTS.SCRIPTURL + "#duck", t);
+ }, "script_url = this bound to an object");
+
+ var baz = "#duck";
+ test(t => {
+ createScriptURLTest('TestPolicyScriptURL7', { createScriptURL: s => getScriptURL(s) }, INPUTS.SCRIPTURL + baz, t);
+ }, "script_url = this without bind");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScriptURL8', null);
+ assert_throws_js(TypeError, _ => {
+ p.createScriptURL(INPUTS.SCRIPTURL);
+ });
+ }, "script_url - calling undefined callback throws");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScriptURL9', { createScriptURL: createScriptURLJS });
+ assert_throws_js(TypeError, _ => {
+ p.createHTML(INPUTS.HTML);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createScript(INPUTS.SCRIPT);
+ });
+ assert_throws_js(TypeError, _ => {
+ p.createURL(INPUTS.URL);
+ });
+ }, "createScriptURL defined - calling undefined callbacks throws");
+
+ test(t => {
+ let p = window.trustedTypes.createPolicy('TestPolicyScriptURL10', {
+ createHTML: createHTMLJSWithThreeArguments,
+ createScript: createScriptJSWithThreeArguments,
+ createScriptURL: createScriptURLJSWithThreeArguments
+ });
+ assert_equals("abc", p.createHTML("a", "b", "c").toString());
+ assert_equals("abc", p.createScript("a", "b", "c").toString());
+ assert_equals("abc", p.createScriptURL("a", "b", "c").toString());
+ assert_equals("abundefined", p.createHTML("a", "b").toString());
+ assert_equals("a123null", p.createScript("a", 123, null).toString());
+ assert_equals("a[object Object]3.14", p.createScriptURL("a", {}, 3.14).toString());
+ }, "Arbitrary number of arguments");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.tentative.html
new file mode 100644
index 0000000000..15728b9888
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.tentative.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types">
+<body>
+<script>
+ //No name given test
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ });
+ }, "No name list given - policy creation throws");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html
new file mode 100644
index 0000000000..d0920497d9
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types * 'none' 'allow-duplicates'">
+<body>
+<script>
+ test(t => {
+ window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ }, "Can create policy with name 'SomeName'");
+
+ test(t => {
+ window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ }, "Can create a second policy with name 'SomeName'");
+
+ test(t => {
+ window.trustedTypes.createPolicy('default', { createHTML: s => s } );
+ }, "Can create policy with name 'default'");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html
new file mode 100644
index 0000000000..48c75937ea
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types 'none'">
+<body>
+<script>
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ });
+ }, "Cannot create policy with name 'SomeName' - policy creation throws");
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ window.trustedTypes.createPolicy('default', { createHTML: s => s } );
+ });
+ }, "Cannot create policy with name 'default' - policy creation throws");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.tentative.html
new file mode 100644
index 0000000000..9200708545
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.tentative.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ //No name given test
+ test(t => {
+ let policy = window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ assert_equals(policy.name, 'SomeName');
+ }, "Wildcard given - policy creation works");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests.tentative.html
new file mode 100644
index 0000000000..3a56546151
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests.tentative.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="trusted-types SomeName JustOneMoreName">
+<body>
+<script>
+ // Allowed name test
+ test(t => {
+ let policy = window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+ assert_equals(policy.name, 'SomeName');
+ }, "Allowed-name policy creation works.");
+
+ // Another allowed name test
+ test(t => {
+ let policy = window.trustedTypes.createPolicy('JustOneMoreName', { createHTML: s => s } );
+ assert_equals(policy.name, 'JustOneMoreName');
+ }, "Another allowed-name policy creation works.");
+
+ // Non-allowed names test
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ window.trustedTypes.createPolicy('SomeOtherName', { createURL: s => s } );
+ });
+ }, "Non-allowed name policy creation throws.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-nameTests.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-nameTests.tentative.html
new file mode 100644
index 0000000000..9fdafb2ccf
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-nameTests.tentative.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy"
+ content="trusted-types SomeName SomeOtherName">
+<body>
+<script>
+ // Policy name test
+ test(t => {
+ let policy = trustedTypes.createPolicy('SomeName', {} );
+ assert_true(policy instanceof TrustedTypePolicy);
+ assert_equals(policy.name, 'SomeName');
+ }, "policy.name = name");
+
+ // Duplicate names test
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ trustedTypes.createPolicy('SomeName', {} );
+ });
+ }, "duplicate policy name attempt throws");
+
+ // Check error messages.
+ test(t => {
+ try {
+ trustedTypes.createPolicy("unknown name", {});
+ } catch (e) {
+ assert_true(e.toString().includes("disallowed"));
+ assert_false(e.toString().includes("already exists"));
+ }
+
+ try {
+ trustedTypes.createPolicy("SomeName", {});
+ } catch (e) {
+ assert_false(e.toString().includes("disallowed"));
+ assert_true(e.toString().includes("already exists"));
+ }
+ }, "Error messages for duplicates and unlisted policies should be different");
+
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-unenforced.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-unenforced.tentative.html
new file mode 100644
index 0000000000..2934448202
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-createPolicy-unenforced.tentative.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+ // This test tests error handling of duplicate policy creation when no
+ // Trusted Types enforcement is active.
+
+ test(t => {
+ trustedTypes.createPolicy('foo', {} );
+ trustedTypes.createPolicy('foo', {} );
+ }, "Duplicate policy names should be tolerated (unless in enforcing mode)");
+
+</script>
+</body>
+
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-defaultPolicy.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-defaultPolicy.tentative.html
new file mode 100644
index 0000000000..7ac09d8bb9
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-defaultPolicy.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ test(t => {
+ assert_equals(window.trustedTypes.defaultPolicy, null);
+ }, "defaultPolicy with no default created is not an error");
+
+ test(t => {
+ let policy = window.trustedTypes.createPolicy('default', { createHTML: s => s } );
+ assert_true(policy instanceof TrustedTypePolicy);
+ assert_equals(policy, window.trustedTypes.defaultPolicy);
+ }, "defaultPolicy returns the correct default policy");
+
+ test(t => {
+ let foo_policy = window.trustedTypes.createPolicy('foo', { createHTML: s => s } );
+ let default_policy = window.trustedTypes.defaultPolicy;
+ window.trustedTypes.defaultPolicy = foo_policy;
+ assert_equals(window.trustedTypes.defaultPolicy, default_policy);
+ assert_not_equals(window.trustedTypes.defaultPolicy, foo_policy);
+ }, "defaultPolicy is a read-only property");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getAttributeType-namespace.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getAttributeType-namespace.tentative.html
new file mode 100644
index 0000000000..0f0d820e28
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getAttributeType-namespace.tentative.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+// Tests for getAttributeType with namespaces, based on
+// https://crbug.com/1305293 (attachment on comment 0).
+
+const parser = new DOMParser();
+[
+ parser.parseFromString(
+ '<!doctype html><html><head><script src="./foo.js"><'+'/script></head></html>',
+ 'text/html'),
+ parser.parseFromString(
+ '<html xmlns="http://www.w3.org/1999/xhtml"><head><script src="./foo.js" /></head></html>',
+ 'application/xhtml+xml'),
+ parser.parseFromString(
+ '<xml xmlns:html="http://www.w3.org/1999/xhtml"><html:script src="./foo.js" /></xml>',
+ 'application/xml')
+].forEach((doc, index) => {
+ const element = doc.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", 'script')[0];
+ const attribute = element.getAttributeNode("src");
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, element.namespaceURI, attribute.namespaceURI),
+ "TrustedScriptURL");
+ }, `${index}: getAttributeType with full namespace info.`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, element.namespaceURI, undefined),
+ "TrustedScriptURL");
+ },`${index}: getAttributeType with element namespace and empty attribute namespace`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, undefined, undefined), "TrustedScriptURL");
+ }, `${index}: getAttributeType without namespaces.`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, undefined, ""), "TrustedScriptURL");
+ }, `${index}: getAttributeType with undefined and empty namespace.`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, "", undefined), "TrustedScriptURL");
+ }, `${index}: getAttributeType with empty and undefined namespace.`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, "", ""), "TrustedScriptURL");
+ }, `${index}: getAttributeType with empty namespaces.`);
+
+ test(_ => {
+ assert_equals(trustedTypes.getAttributeType(
+ element.localName, attribute.name, element.namespaceURI, ""), "TrustedScriptURL");
+ }, `${index}: getAttributeType with element namespace and empty attribute namespace.`);
+});
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html
new file mode 100644
index 0000000000..21aba668cc
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<body>
+<div id="target"></div>
+<script>
+ test(t => {
+ assert_equals(trustedTypes.getPropertyType("script", "text"), "TrustedScript");
+ assert_equals(trustedTypes.getPropertyType("script", "src"), "TrustedScriptURL");
+ assert_equals(trustedTypes.getPropertyType("script", "id"), null);
+ assert_equals(trustedTypes.getPropertyType("script", "b"), null);
+ }, "sanity check trustedTypes.getPropertyType for the HTML script element.");
+
+ test(t => {
+ assert_equals(trustedTypes.getAttributeType("img", "onerror"), "TrustedScript");
+ assert_equals(trustedTypes.getAttributeType("img", "width"), null);
+ assert_equals(trustedTypes.getAttributeType("img", "madeup"), null);
+ }, "sanity check trustedTypes.getAttributeType.");
+
+ test(t => {
+ assert_true(!!trustedTypes.getTypeMapping());
+ }, "sanity check trustedTypes.getTypeMapping");
+
+
+ // getPropertyType tests adapted from w3c/trusted-types polyfill:
+ test(t => {
+ // returns the proper type for attribute-related properties
+ assert_equals(trustedTypes.getPropertyType("script", "src"), "TrustedScriptURL");
+
+ // is case insensitive for tag names
+ assert_equals(trustedTypes.getPropertyType("SCRIPT", "src"), "TrustedScriptURL");
+
+ // is case sensitive for property names
+ assert_equals(trustedTypes.getPropertyType("script", "sRc"), null);
+ assert_equals(trustedTypes.getPropertyType("div", "innerhtml"), null);
+
+ // returns the proper type for innerHTML
+ assert_equals(trustedTypes.getPropertyType("div", "innerHTML"), "TrustedHTML");
+
+ // returns the proper type for outerHTML
+ assert_equals(trustedTypes.getPropertyType("div", "outerHTML"), "TrustedHTML");
+
+ // returns the proper type for script.prop
+ ["text", "innerText", "textContent"].forEach((prop) => {
+ assert_equals(trustedTypes.getPropertyType("script", prop), "TrustedScript");
+ });
+ }, "getPropertyType tests adapted from w3c/trusted-types polyfill");
+
+ test(t => {
+ // returns the proper type
+ assert_equals(trustedTypes.getAttributeType('script', 'src'), 'TrustedScriptURL');
+
+ // ignores attributes from unknown namespaces
+ assert_equals(trustedTypes.getAttributeType(
+ 'a', 'href', '', 'http://foo.bar'), null);
+
+ // is case insensitive for element names
+ assert_equals(trustedTypes.getAttributeType('SCRIPT', 'src'), 'TrustedScriptURL');
+
+ // is case insensitive for the attribute names
+ assert_equals(trustedTypes.getAttributeType('script', 'SRC'), 'TrustedScriptURL');
+
+ // supports the inline event handlers
+ assert_equals(trustedTypes.getAttributeType('img', 'onerror'), 'TrustedScript');
+ assert_equals(trustedTypes.getAttributeType('unknown', 'onerror'), 'TrustedScript');
+
+ // defaults to undefined
+ assert_equals(trustedTypes.getAttributeType('unknown', 'src'), null);
+ assert_equals(trustedTypes.getAttributeType('img', 'bar'), null);
+ }, "getAttributeType tests adapted from w3c/trusted-types polyfill");
+
+
+ test(t=> {
+ const map = trustedTypes.getTypeMapping();
+
+ // Spot testing some values.
+ assert_equals(map["script"].attributes.src, "TrustedScriptURL");
+ assert_equals(map["*"].properties.innerHTML, "TrustedHTML");
+ assert_equals(map["foo"], undefined);
+
+ // getTypeMapping returns a 'clean' object, in case the return value has
+ // been modified.
+ map["*"].attributes["foo"] = "bar";
+ assert_equals(trustedTypes.getTypeMapping()["*"].attributes["foo"], undefined);
+;
+ // Unknown namespaces:
+ assert_equals(trustedTypes.getTypeMapping("http://foo/bar"), null);
+ }, "getTypeMapping tests adapted from w3c/trusted-types polyfill");
+
+ // Test case handling for both attributes and properties.
+ for (let attr of ["codeBase", "CODEBASE", "codebase"]) {
+ for (let elem of ["object", "OBJECT", "oBjEcT"]) {
+ test(t => {
+ // attributes are case-insensitive, so all variants should be defined.
+ assert_true(trustedTypes.getAttributeType(elem, attr) != undefined);
+ }, `${elem}[${attr}] is defined`);
+ test(t => {
+ // properties are case-sensitive, so only the "correct" spelling
+ // should be defined.
+ assert_equals(trustedTypes.getPropertyType(elem, attr) != undefined,
+ attr == "codeBase");
+ }, `${elem}.${attr} is maybe defined`);
+ }
+ }
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html
new file mode 100644
index 0000000000..a7df477d00
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<body>
+<script>
+ // Policy settings for all tests
+ const noopPolicy = {
+ 'createHTML': (s) => s,
+ 'createScriptURL': (s) => s,
+ 'createScript': (s) => s,
+ };
+
+ // isHTML tests
+ test(t => {
+ const p = trustedTypes.createPolicy('html', noopPolicy);
+ let html = p.createHTML(INPUTS.HTML);
+
+ assert_true(trustedTypes.isHTML(html));
+ let html2 = Object.create(html);
+
+ // instanceof can pass, but we rely on isHTML
+ assert_true(html2 instanceof TrustedHTML);
+ assert_false(trustedTypes.isHTML(html2));
+
+ let html3 = Object.assign({}, html, {toString: () => 'fake'});
+
+ assert_false(trustedTypes.isHTML(html3));
+ }, 'TrustedTypePolicyFactory.isHTML requires the object to be created via policy.');
+
+ // isScript tests
+ test(t => {
+ const p = trustedTypes.createPolicy('script', noopPolicy);
+ let script = p.createScript(INPUTS.SCRIPT);
+
+ assert_true(trustedTypes.isScript(script));
+ let script2 = Object.create(script);
+
+ // instanceof can pass, but we rely on isScript
+ assert_true(script2 instanceof TrustedScript);
+ assert_false(trustedTypes.isScript(script2));
+
+ let script3 = Object.assign({}, script, {toString: () => 'fake'});
+
+ assert_false(trustedTypes.isScript(script3));
+ }, 'TrustedTypePolicyFactory.isScript requires the object to be created via policy.');
+
+ // isScriptURL tests
+ test(t => {
+ const p = trustedTypes.createPolicy('script_url', noopPolicy);
+ let script = p.createScriptURL(INPUTS.SCRIPTURL);
+
+ assert_true(trustedTypes.isScriptURL(script));
+ let script2 = Object.create(script);
+
+ // instanceof can pass, but we rely on isScript
+ assert_true(script2 instanceof TrustedScriptURL);
+ assert_false(trustedTypes.isScriptURL(script2));
+
+ let script3 = Object.assign({}, script, {toString: () => 'fake'});
+
+ assert_false(trustedTypes.isScriptURL(script3));
+ }, 'TrustedTypePolicyFactory.isScriptURL requires the object to be created via policy.');
+
+ // Test non-object parameters.
+ test(t => {
+ assert_false(trustedTypes.isHTML(null));
+ assert_false(trustedTypes.isHTML(123));
+ assert_false(trustedTypes.isHTML(0.5));
+ assert_false(trustedTypes.isHTML('test'));
+ assert_false(trustedTypes.isHTML({}));
+ assert_false(trustedTypes.isScript(null));
+ assert_false(trustedTypes.isScript(123));
+ assert_false(trustedTypes.isScript(0.5));
+ assert_false(trustedTypes.isScript('test'));
+ assert_false(trustedTypes.isScript({}));
+ assert_false(trustedTypes.isScriptURL(null));
+ assert_false(trustedTypes.isScriptURL(123));
+ assert_false(trustedTypes.isScriptURL(0.5));
+ assert_false(trustedTypes.isScriptURL('test'));
+ assert_false(trustedTypes.isScriptURL({}));
+ }, 'TrustedTypePolicyFactory.isXXX should accept anything without throwing.');
+</script>
diff --git a/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-metadata.tentative.html b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-metadata.tentative.html
new file mode 100644
index 0000000000..70a5b44666
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/TrustedTypePolicyFactory-metadata.tentative.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+<body>
+<div id="target"></div>
+<script>
+ const policy = trustedTypes.createPolicy("anythinggoes", {
+ "createHTML": x => x,
+ "createScript": x => x,
+ "createScriptURL": x => x,
+ });
+
+ const create_value = {
+ "TrustedHTML": policy.createHTML("hello"),
+ "TrustedScript": policy.createScript("x => x + x"),
+ "TrustedScriptURL": policy.createScriptURL("https://url.invalid/blubb.js"),
+ null: "empty",
+ };
+
+ // The tests will assign all values to all sink types. To prevent spurious
+ // errors when assigning "hello" to a script sink, we'll just define a
+ // varaible of that name.
+ const hello = "";
+
+ // We seed our elements and properties with one element/property that has no
+ // 'trusted type' sinks, and one non-specced (madeup) element/property.
+ // Also add several event handlers (onclick).
+ let elements = ['madeup', 'b'];
+ let properties = ['madeup', 'id', "onerror", "onclick"];
+ const types = [null, "TrustedHTML", "TrustedScript", "TrustedScriptURL"];
+
+ // We'll wrap construction of the elements/properties list in a test, mainly
+ // so we'll get decent error messages when it might fail.
+ test(t => {
+ // Collect all element and property names from getTypeMapping().
+ const map = trustedTypes.getTypeMapping();
+ for (let elem in map) {
+ elements.push(elem);
+ properties = properties.concat(Object.keys(map[elem].properties));
+ }
+
+ // Remove "*" entries and de-duplicate properties.
+ elements = elements.filter(s => !s.includes("*"));
+ properties = properties.filter(s => !s.includes("*"));
+ properties = Array.from(new Set(properties));
+ }, "Prepare parameters for generic test series below.");
+
+ // Iterate one test for each combination of element, property, and sink type.
+ const target = document.getElementById("target");
+ for (elem of elements) {
+ for (property of properties) {
+ for (type of types) {
+ // Conceptually, our test is beautifully simple: Ask getPropertyType
+ // about the expected trusted type. If it's the one we're testing,
+ // expect the assignment to pass, and expect we can read back the same
+ // value. If it's a different type, expect the assignment to fail.
+ //
+ // The idealized test case would look something like this:
+ // const value = ....;
+ // const test_fn = _ => { element[property] = value };
+ // if (type == expected_type || !expected_type) {
+ // test_fn();
+ // assert_equals(element[property], value);
+ // } else {
+ // assert_throws_js(..., test_fn, ...);
+ // }
+ //
+ // Below is the same logic, but extended to handle the various edge
+ // cases.
+ //
+ // Some difficulties we need to accomodate:
+ // - Some properties have built-in behaviours. (E.g. the "innerHTML"
+ // value depends on whether elements are visible or not.) To
+ // accomodate this, we have a big switch-statement that handles
+ // those types of exceptions.
+ // - Some properties parse their values, so that you can't easily get
+ // the original text value back (e.g. error handlers).
+ // - Some properties cause actions as side-effects (e.g. loading a
+ // script), which will cause errors in the test (despite the actual
+ // code-under-test meeting our expectations). This is handled with
+ // a cleanup script which removes the element (and thus cancels
+ // the loading actions).
+ test(t => {
+ const element = target.appendChild(document.createElement(elem));
+ t.add_cleanup(_ => element.remove());
+ const expected_type = trustedTypes.getPropertyType(elem, property);
+ const value = create_value[type];
+ const test_fn = _ => { element[property] = value; };
+ if (type == expected_type || !expected_type) {
+ test_fn();
+ let result_value = element[property];
+ switch (property) {
+ // Node.innerText returns the rendered text of an Element, which
+ // in this test case is usually empty. For this specific case,
+ // let's just check "textContent" instead.
+ // Node.innerHTML re-creates a text representation from the DOM,
+ // which may not always match the exact input.
+ case "innerText":
+ case "innerHTML":
+ result_value = element["textContent"];
+ break;
+ // Node.outerHTML replaces the node, which means the simple
+ // checking logic below does not work. In this case, we'll just
+ // return and hence skip the result comparison.
+ case "outerHTML":
+ return;
+ // URL-typed accessors
+ case "src":
+ if (elem == "iframe")
+ return;
+ break;
+ // Properties starting with "on" are usually error handlers,
+ // which will parse their input as a function. In this case,
+ // also skip the result comparison.
+ default:
+ if (property.startsWith("on")) return;
+ break;
+ }
+ assert_equals("" + result_value, "" + value);
+ } else {
+ assert_throws_js(TypeError, test_fn, "throws");
+ }
+ }, `Test assignment of ${type ? type : "string"} on ${elem}.${property}`);
+
+ // And once more, for attributes.
+ test(t => {
+ const element = target.appendChild(document.createElement(elem));
+ t.add_cleanup(_ => element.remove());
+ const expected_type = trustedTypes.getAttributeType(elem, property);
+ const value = create_value[type];
+ const test_fn = _ => { element.setAttribute(property, value); };
+ if (type == expected_type || !expected_type) {
+ test_fn();
+ assert_equals("" + element.getAttribute(property), "" + value);
+ } else if (elem == "script" && (property == "innerText" ||
+ property == "textContent" || property == "text")) {
+ // Due to the "slot setting" mechnanism, setting script's innerText,
+ // textContent and text attributes dosn't throw. So we can't use
+ // that in our tests.
+ // ref: https://w3c.github.io/trusted-types/dist/spec/#setting-slot-values
+ test_fn();
+ } else {
+ assert_throws_js(TypeError, test_fn, "throws");
+ }
+ }, `Test assignment of ${type ? type : "string"} on ${elem}.setAttribute(${property},..)`);
+ }
+ }
+ }
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/Window-TrustedTypes.tentative.html b/testing/web-platform/tests/trusted-types/Window-TrustedTypes.tentative.html
new file mode 100644
index 0000000000..718c763afa
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/Window-TrustedTypes.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<body>
+<script>
+ test(t => {
+ let factory = window.trustedTypes;
+ assert_true(factory instanceof TrustedTypePolicyFactory);
+ }, "factory = window.trustedTypes");
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ let factory = new TrustedTypePolicyFactory();
+ });
+ }, "factory construction fails");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/WorkerGlobalScope-eval.html b/testing/web-platform/tests/trusted-types/WorkerGlobalScope-eval.html
new file mode 100644
index 0000000000..9248784924
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/WorkerGlobalScope-eval.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+<head>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<script>
+
+// To test workers, we need to importScripts source files in the workers.
+// Since the point of this test is to test blocking of importScripts, we need
+// to set up one policy that will blindly pass through URLs for use in the test
+// setup, and then have additional policies for the actual test cases.
+//
+// For the same reason we cannot use the otherwise preferred 'META: workers'
+// tag, since that test setup would be blocked as soon as trusted types
+// enforcement is enabled.
+const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", {
+ createScriptURL: x => x});
+const test_url =
+ test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js");
+
+fetch_tests_from_worker(new Worker(test_url));
+
+fetch_tests_from_worker(new SharedWorker(test_url));
+
+// Cargo-culted from code generated from "META: worker".
+if ('serviceWorker' in navigator) {
+ (async function() {
+ const scope = 'support/some/scope/for/this/test';
+ let reg = await navigator.serviceWorker.getRegistration(scope);
+ if (reg) await reg.unregister();
+ reg = await navigator.serviceWorker.register(test_url, {scope});
+ fetch_tests_from_worker(reg.installing);
+ })();
+}
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/WorkerGlobalScope-importScripts.html b/testing/web-platform/tests/trusted-types/WorkerGlobalScope-importScripts.html
new file mode 100644
index 0000000000..9853b1bc44
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/WorkerGlobalScope-importScripts.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+<head>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<script>
+
+// To test workers, we need to importScripts source files in the workers.
+// Since the point of this test is to test blocking of importScripts, we need
+// to set up one policy that will blindly pass through URLs for use in the test
+// setup, and then have additional policies for the actual test cases.
+//
+// For the same reason we cannot use the otherwise preferred 'META: workers'
+// tag, since that test setup would be blocked as soon as trusted types
+// enforcement is enabled.
+const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", {
+ createScriptURL: x => x});
+const test_url =
+ test_setup_policy.createScriptURL("support/WorkerGlobalScope-importScripts.https.js");
+
+fetch_tests_from_worker(new Worker(test_url));
+
+fetch_tests_from_worker(new SharedWorker(test_url));
+
+// Cargo-culted from code generated from "META: worker".
+if ('serviceWorker' in navigator) {
+ (async function() {
+ const scope = 'support/some/scope/for/this/test';
+ let reg = await navigator.serviceWorker.getRegistration(scope);
+ if (reg) await reg.unregister();
+ reg = await navigator.serviceWorker.register(test_url, {scope});
+ fetch_tests_from_worker(reg.installing);
+ })();
+}
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/block-Document-execCommand.tentative.html b/testing/web-platform/tests/trusted-types/block-Document-execCommand.tentative.html
new file mode 100644
index 0000000000..87759cdc19
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-Document-execCommand.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+<link rel="author" title="Daniel Vogelheim" href="mailto:vogelheim@chromium.org"></link>
+<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/"></link>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+ // Tests that certain execCommand commands will observe Trusted Types if
+ // it's enforced.
+ const commands = [ "insertHTML", "paste" ];
+ const tt_commands = [ "insertHTML" ];
+
+ // A pass-through policy for testing.
+ const a_policy = trustedTypes.createPolicy("a policy", {"createHTML": x => x});
+
+ for (const command of commands) {
+ const requires_tt = tt_commands.includes(command);
+
+ // Test that execCommand with String throws, but only for commands that
+ // require TT.
+ if (requires_tt) {
+ test(t => {
+ assert_throws_js(TypeError, _ => document.execCommand(command, false, "<em>Hello World</em>"));
+ }, `Document.execCommand("${command}") throws.`);
+ } else {
+ test(t => {
+ document.execCommand(command, false, "<em>Hello World</em>");
+ }, `Document.execCommand("${command}") works as usual."`);
+ }
+ // Test that execCommand succeeds with a TrustedHTML argument.
+ test(t => {
+ document.execCommand(command, false, a_policy.createHTML("<em>Hello World</em>"));
+ }, `Document.execCommand("${command}") works with a TrustedHTML argument.`);
+ }
+
+ // Test that with a default policy, all comamnds will work again.
+ trustedTypes.createPolicy("default", {"createHTML": x => x});
+ for (const command of commands) {
+ test(t => {
+ document.execCommand(command, false, "<em>Hello World</em>");
+ }, `Document.execCommand("${command}") works as usual with a default policy.`);
+ }
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-Node-multiple-arguments.tentative.html b/testing/web-platform/tests/trusted-types/block-Node-multiple-arguments.tentative.html
new file mode 100644
index 0000000000..c3e7671534
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-Node-multiple-arguments.tentative.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<div id="container"></div>
+<script>
+ 'use strict';
+ const container = document.querySelector("#container");
+ const policy = window.trustedTypes.createPolicy("policy", {
+ createScript: t => t,
+ });
+ function stringify(arg) {
+ return "textContent" in Object.getPrototypeOf(arg) ? arg.textContent : arg.toString()
+ }
+
+ // Test all combinations of:
+ // - DOM methods: append, prepend, replaceWith, after, before
+ // - one or two parameters, string, Text node, Trusted Script
+ // - into regular container or <script> element.
+ //
+ // Test arguments are all string literals with a semicolon, because -
+ // depending on target - it might be injected into a <script> and shouldn't
+ // cause syntax errors there.
+ const targets = ["div", "script"];
+ const pass_args = [
+ [ policy.createScript("'createScript';") ],
+ [ policy.createScript("'createScript #1';"), policy.createScript("'#2;'") ],
+ ];
+ const fail_args = [
+ [ "'plain text';" ],
+ [ "'plain text #1';", "'plain text #2';" ],
+ [ document.createTextNode("'node';") ],
+ [ document.createTextNode("'node #1';"),
+ document.createTextNode("'node #2';") ],
+ [ "'mixed';", document.createTextNode("'node';") ],
+ [ "'mixed';", policy.createScript("'script';") ],
+ [ document.createTextNode("'node';"),
+ policy.createScript("'script';") ],
+ ];
+ const all_args = [].concat(pass_args).concat(fail_args);
+
+ for (const target of targets) {
+ for (const args of all_args) {
+ var should_fail = target == "script" && fail_args.indexOf(args) != -1;
+ var fail_string = should_fail ? "fail" : "pass";
+
+ for (const setter of [container.replaceWith, container.after, container.before]) {
+ test(t => {
+ var outer = document.createElement(target);
+ container.appendChild(outer);
+ var inner = document.createElement("p");
+ outer.appendChild(inner);
+ var test_fn = _ => { setter.apply(inner, args); };
+ var expected;
+ if (should_fail) {
+ assert_throws_js(TypeError, test_fn, "This should throw.");
+ expected = "";
+ } else {
+ test_fn();
+ expected = args.map(stringify).join("");
+ }
+ assert_equals(outer.textContent, expected);
+ }, `${setter.name}(${args.toString()}) on <${target}> should ${fail_string}`);
+ }
+
+ for (const setter of [container.append, container.prepend]) {
+ test(t => {
+ let outer = document.createElement(target);
+ container.appendChild(outer);
+ var test_fn = _ => { setter.apply(outer, args); };
+ var expected;
+ if (should_fail) {
+ assert_throws_js(TypeError, test_fn, "This should throw.");
+ expected = "";
+ } else {
+ test_fn();
+ expected = args.map(stringify).join("");
+ }
+ assert_equals(outer.textContent, expected);
+ }, `${setter.name}(${args.toString()}) on <${target}> should ${fail_string}`);
+ }
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMParser-parseFromString.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMParser-parseFromString.tentative.html
new file mode 100644
index 0000000000..dd912e6b8d
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMParser-parseFromString.tentative.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+<body>
+<script>
+ // Trusted HTML assignments do not throw.
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ let parser = new DOMParser();
+ let doc = parser.parseFromString(html, "text/html");
+ assert_equals(doc.body.innerText, RESULTS.HTML);
+ }, "document.innerText assigned via policy (successful HTML transformation).");
+
+ // String assignments throw.
+ test(t => {
+ var parser = new DOMParser();
+ assert_throws_js(TypeError, _ => {
+ var doc = parser.parseFromString("Fail", "text/html");
+ });
+ }, "`document.innerText = string` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ var parser = new DOMParser();
+ assert_throws_js(TypeError, _ => {
+ var doc = parser.parseFromString(null, "text/html");
+ });
+ }, "'document.innerText = null' throws");
+
+ // After default policy creation string assignment implicitly calls createHTML.
+ test(t => {
+ let p = window.trustedTypes.createPolicy("default", { createHTML: createHTMLJS }, true);
+ let parser = new DOMParser();
+ let doc = parser.parseFromString(INPUTS.HTML, "text/html");
+ assert_equals(doc.body.innerText, RESULTS.HTML);
+ }, "'document.innerText = string' assigned via default policy (successful HTML transformation).");
+
+ // After default policy creation null assignment implicitly calls createHTML.
+ test(t => {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(null, "text/html");
+ assert_equals(doc.body.innerText, "null");
+ }, "'document.innerText = null' assigned via default policy does not throw");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.tentative.html
new file mode 100644
index 0000000000..c24715718d
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.tentative.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+<body>
+<script>
+ // setTimeout tests
+ // TrustedScript assignments do not throw.
+ async_test(t => {
+ window.timeoutTest = t;
+ let policy = createScript_policy(window, 'timeout');
+ let script = policy.createScript("window.timeoutTest.done();");
+ setTimeout(script);
+ }, "window.setTimeout assigned via policy (successful Script transformation).");
+
+ // String assignments throw.
+ test(t => {
+ window.timeoutTestString = t.unreached_func();
+ assert_throws_js(TypeError, _ => {
+ setTimeout("window.timeoutTestString();");
+ });
+ }, "`window.setTimeout(string)` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ setTimeout(null);
+ });
+ }, "`window.setTimeout(null)` throws.");
+
+ // setInterval tests
+ // TrustedScript assignments do not throw.
+ async_test(t => {
+ window.intervalTest = t;
+ let policy = createScript_policy(window, 'script');
+ let script = policy.createScript("window.intervalTest.done();");
+ setInterval(script);
+ }, "window.setInterval assigned via policy (successful Script transformation).");
+
+ // String assignments throw.
+ test(t => {
+ window.intervalTestString = t.unreached_func();
+ assert_throws_js(TypeError, _ => {
+ setInterval("window.intervalTestString()");
+ });
+ }, "`window.setInterval(string)` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ setInterval(null);
+ });
+ }, "`window.setInterval(null)` throws.");
+
+ let policy = window.trustedTypes.createPolicy("default", { createScript: x => "0" });
+ // After default policy creation string assignment implicitly calls createScript.
+ test(t => {
+ setTimeout(INPUTS.SCRIPT);
+ setInterval(INPUTS.SCRIPT);
+ }, "`setTimeout(string)`, `setInterval(string)` via default policy (successful Script transformation).");
+ // After default policy creation null assignment implicitly calls createScript.
+ test(t => {
+ setTimeout(null);
+ setInterval(null);
+ }, "`setTimeout(null)`, `setInterval(null)` via default policy (successful Script transformation).");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Document-write.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Document-write.tentative.html
new file mode 100644
index 0000000000..974203c113
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Document-write.tentative.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<script>
+ // TrustedURL assignments do not throw.
+ let p = createHTML_policy(window, 1);
+ test(t => {
+ document.body.innerText = '';
+ let html = p.createHTML(INPUTS.HTML);
+ document.write(html);
+ assert_equals(document.body.innerText, RESULTS.HTML);
+ }, "document.write with html assigned via policy (successful URL transformation).");
+
+ // TrustedURL assignments do not throw. (Now for writeln.)
+ test(t => {
+ document.body.innerText = '';
+ let html = p.createHTML(INPUTS.HTML);
+ document.writeln(html);
+ assert_equals(document.body.innerText, RESULTS.HTML);
+ }, "document.writeln with html assigned via policy (successful URL transformation).");
+
+ // String assignments throw.
+ test(t => {
+ const old = document.body.innerText;
+ assert_throws_js(TypeError, _ => {
+ document.write('A string');
+ });
+ assert_equals(document.body.innerText, old);
+ }, "`document.write(string)` throws");
+
+ // String assignments throw. (Now for writeln.)
+ test(t => {
+ const old = document.body.innerText;
+ assert_throws_js(TypeError, _ => {
+ document.writeln('A string');
+ });
+ assert_equals(document.body.innerText, old);
+ }, "`document.writeln(string)` throws");
+
+ // Null assignment throws.
+ test(t => {
+ const old = document.body.innerText;
+ assert_throws_js(TypeError, _ => {
+ document.write(null);
+ });
+ assert_equals(document.body.innerText, old);
+ }, "`document.write(null)` throws");
+
+ // Null assignment throws. (Now for writeln.)
+ test(t => {
+ const old = document.body.innerText;
+ assert_throws_js(TypeError, _ => {
+ document.writeln(null);
+ });
+ assert_equals(document.body.innerText, old);
+ }, "`document.writeln(null)` throws");
+
+ let default_policy = trustedTypes.createPolicy('default',
+ { createHTML: createHTMLJS }, true );
+
+ // Default policy works.
+ test(t => {
+ document.body.innerText = '';
+ document.write(INPUTS.HTML);
+ assert_equals(document.body.innerText, RESULTS.HTML);
+ }, "`document.write(string)` observes default policy");
+
+ // Default policy works. (Now for writeln.)
+ test(t => {
+ document.body.innerText = '';
+ document.writeln(INPUTS.HTML);
+ assert_equals(document.body.innerText, RESULTS.HTML);
+ }, "`document.writeln(string)` observes default policy");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-insertAdjacentHTML.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-insertAdjacentHTML.tentative.html
new file mode 100644
index 0000000000..228887d042
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-insertAdjacentHTML.tentative.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<div id="container"></div>
+<script>
+ var container = document.querySelector('#container');
+
+ // Trusted HTML assignments do not throw.
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ let before = 'before';
+ let after = 'after';
+ let htmlBefore = p.createHTML(before);
+ let htmlAfter = p.createHTML(after);
+
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ d.insertAdjacentHTML('beforebegin', html);
+ assert_equals(d.previousSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.previousSibling.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('afterbegin', htmlBefore);
+ d.insertAdjacentHTML('beforeend', htmlAfter);
+ assert_equals(d.innerHTML, before + after);
+
+ d.insertAdjacentHTML('afterend', html);
+ assert_equals(d.nextSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.nextSibling.data, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "insertAdjacentHTML with html assigned via policy (successful HTML transformation).");
+
+ // String assignments throw.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('beforebegin', "<p>Fail</p>");
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('afterbegin', "<p>Fail</p>");
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('beforeend', "<p>Fail</p>");
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('afterend', "<p>Fail</p>");
+ });
+
+ assert_equals(d.previousSibling, null);
+ assert_equals(d.firstChild, null);
+ assert_equals(d.lastChild, null);
+ assert_equals(d.nextSibling, null);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`insertAdjacentHTML(string)` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('beforebegin', null);
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('afterbegin', null);
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('beforeend', null);
+ });
+ assert_throws_js(TypeError, _ => {
+ d.insertAdjacentHTML('afterend', null);
+ });
+
+ assert_equals(d.previousSibling, null);
+ assert_equals(d.firstChild, null);
+ assert_equals(d.lastChild, null);
+ assert_equals(d.nextSibling, null);
+ }, "`insertAdjacentHTML(null)` throws.");
+
+ // After default policy creation string assignment implicitly calls createHTML.
+ test(t => {
+ let p = window.trustedTypes.createPolicy("default", { createHTML: createHTMLJS }, true);
+
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ d.insertAdjacentHTML('beforebegin', INPUTS.HTML);
+ assert_equals(d.previousSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.previousSibling.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('afterbegin', INPUTS.HTML);
+ assert_equals(d.firstChild.nodeType, Node.TEXT_NODE);
+ assert_equals(d.firstChild.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('beforeend', INPUTS.HTML);
+ assert_equals(d.lastChild.nodeType, Node.TEXT_NODE);
+ assert_equals(d.lastChild.data, RESULTS.HTML);
+
+ d.insertAdjacentHTML('afterend', INPUTS.HTML);
+ assert_equals(d.nextSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.nextSibling.data, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`insertAdjacentHTML(string)` assigned via default policy (successful HTML transformation).");
+
+ // After default policy creation null assignment implicitly calls createHTML.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+
+ d.insertAdjacentHTML('beforebegin', null);
+ assert_equals(d.previousSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.previousSibling.data, "null");
+
+ d.insertAdjacentHTML('afterbegin', null);
+ assert_equals(d.firstChild.nodeType, Node.TEXT_NODE);
+ assert_equals(d.firstChild.data, "null");
+
+ d.insertAdjacentHTML('beforeend', null);
+ assert_equals(d.lastChild.nodeType, Node.TEXT_NODE);
+ assert_equals(d.lastChild.data, "null");
+
+ d.insertAdjacentHTML('afterend', null);
+ assert_equals(d.nextSibling.nodeType, Node.TEXT_NODE);
+ assert_equals(d.nextSibling.data, "null");
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`insertAdjacentHTML(null)` assigned via default policy does not throw.");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-outerHTML.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-outerHTML.tentative.html
new file mode 100644
index 0000000000..9b6cf72cb4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-outerHTML.tentative.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<div id="container"></div>
+<script>
+ var container = document.querySelector('#container')
+
+ // TrustedHTML assignments do not throw.
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+
+ var d = document.createElement('div');
+ document.querySelector('#container').appendChild(d);
+ d.outerHTML = html;
+ assert_equals(container.innerText, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "outerHTML with html assigned via policy (successful HTML transformation).");
+
+ // String assignments throw.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+ assert_throws_js(TypeError, _ => {
+ d.outerHTML = "Fail.";
+ });
+ assert_equals(container.innerText, "");
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`outerHTML = string` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+ assert_throws_js(TypeError, _ => {
+ d.outerHTML = null;
+ });
+ assert_equals(container.innerText, "");
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`outerHTML = null` throws.");
+
+ // After default policy creation string assignment implicitly calls createHTML.
+ test(t => {
+ let p = window.trustedTypes.createPolicy("default", { createHTML: createHTMLJS }, true);
+
+ var d = document.createElement('div');
+ document.querySelector('#container').appendChild(d);
+ d.outerHTML = INPUTS.HTML;
+ assert_equals(container.innerText, RESULTS.HTML);
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`outerHTML = string` assigned via default policy (successful HTML transformation).");
+
+ // After default policy creation null assignment implicitly calls createHTML.
+ test(t => {
+ var d = document.createElement('div');
+ container.appendChild(d);
+ d.outerHTML = null;
+ assert_equals(container.innerText, "");
+
+ while (container.firstChild)
+ container.firstChild.remove();
+ }, "`outerHTML = null` assigned via default policy does not throw");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html
new file mode 100644
index 0000000000..1d39a804f3
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<script>
+ const nullPolicy = trustedTypes.createPolicy('NullPolicy', {createScript: s => s});
+
+ // TrustedScriptURL Assignments
+ const scriptURLTestCases = [
+ [ 'embed', 'src' ],
+ [ 'object', 'data' ],
+ [ 'object', 'codeBase' ],
+ [ 'script', 'src' ]
+ ];
+
+ scriptURLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_script_url_explicit_set(window,
+ c[0] + "-" + c[1], t, c[0], c[1], RESULTS.SCRIPTURL);
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], null);
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], nullPolicy.createScript('script'));
+ }, c[0] + "." + c[1] + " accepts only TrustedScriptURL");
+ });
+
+ // TrustedHTML Assignments
+ const HTMLTestCases = [
+ [ 'iframe', 'srcdoc' ]
+ ];
+
+ HTMLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_html_explicit_set(window, c[0] + "-" + c[1], t, c[0], c[1], RESULTS.HTML);
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], null);
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], nullPolicy.createScript('script'));
+ }, c[0] + "." + c[1] + " accepts only TrustedHTML");
+ });
+
+ // TrustedScript Assignments
+ const ScriptTestCases = [
+ [ 'div', 'onclick' ]
+ ];
+
+ ScriptTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_script_explicit_set(window, c[0] + "-" + c[1], t, c[0], c[1], RESULTS.SCRIPT);
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type_explicit_set(c[0], c[1], null);
+ }, c[0] + "." + c[1] + " accepts only TrustedScript");
+ });
+
+ test(t => {
+ let el = document.createElement('script');
+
+ assert_throws_js(TypeError, _ => {
+ el.setAttribute('SrC', INPUTS.URL);
+ });
+
+ assert_equals(el.src, '');
+ }, "`Script.prototype.setAttribute.SrC = string` throws.");
+
+ // After default policy creation string and null assignments implicitly call createXYZ
+ let p = window.trustedTypes.createPolicy("default", { createScriptURL: createScriptURLJS, createHTML: createHTMLJS, createScript: createScriptJS }, true);
+ scriptURLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_type(c[0], c[1], INPUTS.SCRIPTURL, RESULTS.SCRIPTURL);
+ assert_element_accepts_trusted_type(c[0], c[1], null, window.location.toString().replace(/[^\/]*$/, "null"));
+ }, c[0] + "." + c[1] + " accepts string and null after default policy was created.");
+ });
+
+ HTMLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_type(c[0], c[1], INPUTS.HTML, RESULTS.HTML);
+ assert_element_accepts_trusted_type(c[0], c[1], null, "null");
+ }, c[0] + "." + c[1] + " accepts string and null after default policy was created.");
+ });
+
+ ScriptTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_type_explicit_set(c[0], c[1], INPUTS.SCRIPT, RESULTS.SCRIPT);
+ assert_element_accepts_trusted_type_explicit_set(c[0], c[1], null, "null");
+ }, c[0] + "." + c[1] + " accepts string and null after default policy was created.");
+ });
+
+ // Other attributes can be assigned with TrustedTypes or strings or null values
+ test(t => {
+ assert_element_accepts_non_trusted_type_explicit_set('a', 'rel', 'A string', 'A string');
+ }, "a.rel accepts strings");
+
+ test(t => {
+ assert_element_accepts_non_trusted_type_explicit_set('a', 'rel', null, 'null');
+ }, "a.rel accepts null");
+
+ test(t => {
+ let embed = document.createElement('embed');
+ let script = document.createElement('script');
+
+ embed.setAttribute('src', INPUTS.SCRIPTURL);
+ let attr = embed.getAttributeNode('src');
+ embed.removeAttributeNode(attr);
+ script.setAttributeNode(attr);
+
+ assert_equals(script.getAttribute('src'), RESULTS.SCRIPTURL);
+ }, "`script.src = setAttributeNode(embed.src)` with string works.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html
new file mode 100644
index 0000000000..346e077a66
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<script>
+ test(t => {
+ assert_element_accepts_trusted_html_set_ns(window, '0', t, 'a', 'b', RESULTS.HTML);
+ }, "Element.setAttributeNS assigned via policy (successful HTML transformation)");
+
+ test(t => {
+ assert_element_accepts_trusted_script_set_ns(window, '1', t, 'a', 'b', RESULTS.SCRIPT);
+ }, "Element.setAttributeNS assigned via policy (successful Script transformation)");
+
+ test(t => {
+ assert_element_accepts_trusted_script_url_set_ns(window, '2', t, 'a', 'b', RESULTS.SCRIPTURL);
+ }, "Element.setAttributeNS assigned via policy (successful ScriptURL transformation)");
+
+ // Unknown, namespaced attributes should not be TT checked:
+ test(t => {
+ assert_element_accepts_non_trusted_type_set_ns('a', 'b', 'A string', 'A string');
+ }, "Element.setAttributeNS accepts untrusted string for non-specced accessor");
+
+ test(t => {
+ assert_element_accepts_non_trusted_type_set_ns('a', 'b', null, 'null');
+ }, "Element.setAttributeNS accepts null for non-specced accessor");
+
+ // Setup trusted values for use in subsequent tests.
+ const script_url = createScriptURL_policy(window, '5').createScriptURL(INPUTS.ScriptURL);
+ const html = createHTML_policy(window, '6').createHTML(INPUTS.HTML);
+ const script = createScript_policy(window, '7').createScript(INPUTS.Script);
+
+ const xlink = "http://www.w3.org/1999/xlink";
+ const svg = "http://www.w3.org/2000/svg";
+
+ // svg:script xlink:href=... expects a TrustedScriptURL.
+ // Assigning a TrustedScriptURL works.
+ test(t => {
+ let elem = document.createElementNS(svg, "script");
+ elem.setAttributeNS(xlink, "href", script_url);
+ assert_equals("" + RESULTS.ScriptURL,
+ elem.getAttributeNodeNS(xlink, "href").value);
+ }, "Assigning TrustedScriptURL to <svg:script xlink:href=...> works");
+
+ // Assigning things that ought to not work.
+ test(t => {
+ let elem = document.createElementNS(svg, "script");
+ const values = [ "abc", null, html, script ];
+ for (const v of values) {
+ assert_throws_js(TypeError, _ => {
+ elem.setAttributeNS(xlink, "href", v);
+ });
+ }
+ }, "Blocking non-TrustedScriptURL assignment to <svg:script xlink:href=...> works");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-HTMLElement-generic.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-HTMLElement-generic.tentative.html
new file mode 100644
index 0000000000..9e780c1ed2
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-HTMLElement-generic.tentative.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<script>
+ var testnb = 0;
+ // TrustedScriptURL Assignments
+ const scriptURLTestCases = [
+ [ 'embed', 'src' ],
+ [ 'object', 'codeBase' ],
+ [ 'object', 'data' ],
+ [ 'script', 'src' ]
+ ];
+
+ testnb = 0;
+ scriptURLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_script_url(window, ++testnb, t, c[0], c[1], RESULTS.SCRIPTURL);
+ assert_throws_no_trusted_type(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type(c[0], c[1], null);
+ }, c[0] + "." + c[1] + " accepts only TrustedScriptURL");
+ });
+
+ // TrustedHTML Assignments
+ const HTMLTestCases = [
+ [ 'div', 'innerHTML' ],
+ [ 'iframe', 'srcdoc' ]
+ ];
+
+ testnb = 0;
+ HTMLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_html(window, ++testnb, t, c[0], c[1], RESULTS.HTML);
+ assert_throws_no_trusted_type(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type(c[0], c[1], null);
+ }, c[0] + "." + c[1] + " accepts only TrustedHTML");
+ });
+
+ // After default policy creation string and null assignments implicitly call createHTML
+ let p = window.trustedTypes.createPolicy("default", { createScriptURL: createScriptURLJS, createHTML: createHTMLJS }, true);
+
+ scriptURLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_type(c[0], c[1], INPUTS.SCRIPTURL, RESULTS.SCRIPTURL);
+ assert_element_accepts_trusted_type(c[0], c[1], null, window.location.toString().replace(/[^\/]*$/, "null"));
+ }, c[0] + "." + c[1] + " accepts string and null after default policy was created");
+ });
+
+
+ HTMLTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_type(c[0], c[1], INPUTS.HTML, RESULTS.HTML);
+ assert_element_accepts_trusted_type(c[0], c[1], null, c[1] === 'innerHTML'? "" : "null");
+ }, c[0] + "." + c[1] + " accepts string and null after default policy was created");
+ });
+
+ // TrustedScript Assignments
+ const scriptTestCases = [
+ [ 'script', 'text' ],
+ [ 'script', 'innerText' ],
+ [ 'script', 'textContent' ]
+ ];
+
+ testnb = 0;
+ scriptTestCases.forEach(c => {
+ test(t => {
+ assert_element_accepts_trusted_script(window, ++testnb, t, c[0], c[1], RESULTS.SCRIPT);
+ assert_throws_no_trusted_type(c[0], c[1], 'A string');
+ assert_throws_no_trusted_type(c[0], c[1], null);
+ }, c[0] + "." + c[1] + " accepts only TrustedScript");
+ });
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-Range-createContextualFragment.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Range-createContextualFragment.tentative.html
new file mode 100644
index 0000000000..7911120493
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-Range-createContextualFragment.tentative.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+<body>
+<script>
+ // TrustedHTML assignments do not throw.
+ test(t => {
+ let p = createHTML_policy(window, 1);
+ let html = p.createHTML(INPUTS.HTML);
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ var result = range.createContextualFragment(html);
+ assert_equals(result.textContent, RESULTS.HTML);
+ }, "range.createContextualFragment assigned via policy (successful HTML transformation).");
+
+ // String assignments throw.
+ test(t => {
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ assert_throws_js(TypeError, _ => {
+ var result = range.createContextualFragment("A string");
+ });
+ }, "`range.createContextualFragment(string)` throws.");
+
+ // Null assignment throws.
+ test(t => {
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ assert_throws_js(TypeError, _ => {
+ var result = range.createContextualFragment(null);
+ });
+ }, "`range.createContextualFragment(null)` throws.");
+
+ // After default policy creation string assignment implicitly calls createHTML
+ test(t => {
+ let p = window.trustedTypes.createPolicy("default", { createHTML: createHTMLJS }, true);
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ var result = range.createContextualFragment(INPUTS.HTML);
+ assert_equals(result.textContent, RESULTS.HTML);
+ }, "`range.createContextualFragment(string)` assigned via default policy (successful HTML transformation).");
+
+ // After default policy creation null assignment implicitly calls createHTML
+ test(t => {
+ var range = document.createRange();
+ range.selectNodeContents(document.documentElement);
+ var result = range.createContextualFragment(null);
+ assert_equals(result.textContent, "null");
+ }, "`range.createContextualFragment(null)` assigned via default policy does not throw.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/block-string-assignment-to-attribute-via-attribute-node.tentative.html b/testing/web-platform/tests/trusted-types/block-string-assignment-to-attribute-via-attribute-node.tentative.html
new file mode 100644
index 0000000000..b881e8cb37
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-string-assignment-to-attribute-via-attribute-node.tentative.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<div id="testcases">
+ <embed src="x"></embed>
+ <object data="x"></object>
+ <object codeBase="x"></object>
+ <script src="x"></script>
+ <iframe srcdoc="x"></iframe>
+ <div onclick="x"></div>
+</div>
+<div id="sanitycheck">
+ <div style=sdf></div>
+ <p class=""></p>
+</div>
+<script>
+test(t => {
+ const nodes = document.querySelectorAll("#sanitycheck *");
+ nodes[0].attributes[0].textContent = "xxx";
+ nodes[1].attributes[0].nodeValue = "yyy";
+}, "Sanity check: Setting non-TT attributes still works.");
+
+for (const element of document.querySelectorAll("#testcases *")) {
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ element.attributes[0].textContent = "sldkjsfldk";
+ });
+ }, `Set ${element.localName}.${element.attributes[0].localName} via textContent`);
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ element.attributes[0].nodeValue = "sdflkgjdlkgjdg";
+ });
+ }, `Set ${element.localName}.${element.attributes[0].localName} via nodeValue`);
+};
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/block-text-node-insertion-into-script-element.tentative.html b/testing/web-platform/tests/trusted-types/block-text-node-insertion-into-script-element.tentative.html
new file mode 100644
index 0000000000..08e3e69553
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/block-text-node-insertion-into-script-element.tentative.html
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<div id="container"></div>
+<script id="script1">"hello world!";</script>
+<script id="trigger"></script>
+<script>
+ var container = document.querySelector("#container");
+ const policy_dict = {
+ createScript: s => (s.includes("fail") ? null : s.replace("default", "count")),
+ createHTML: s => s.replace(/2/g, "3"),
+ };
+ const policy = trustedTypes.createPolicy("policy", policy_dict);
+
+ // Regression tests for 'Bypass via insertAdjacentText', reported at
+ // https://github.com/w3c/trusted-types/issues/133
+
+ // We are trying to assert that scripts do _not_ get executed. We
+ // accomplish by having the script under examination containing a
+ // postMessage, and to send a second guaranteed-to-execute postMessage
+ // so there's a point in time when we're sure the first postMessage
+ // must have arrived (if indeed it had been sent).
+ //
+ // We'll interpret the message data as follows:
+ // - includes "block": error (this message should have been blocked by TT)
+ // - includes "count": Count these, and later check against expect_count.
+ // - includes "done": Unregister the event handler and finish the test.
+ // - all else: Reject, as this is probably an error in the test.
+ function checkMessage(expect_count) {
+ postMessage("done", "*");
+ return new Promise((resolve, reject) => {
+ let count = 0;
+ globalThis.addEventListener("message", function handler(e) {
+ if (e.data.includes("block")) {
+ reject(`'block' received (${e.data})`);
+ } else if (e.data.includes("count")) {
+ count = count + 1;
+ } else if (e.data.includes("done")) {
+ globalThis.removeEventListener("message", handler);
+ if (expect_count && count != expect_count) {
+ reject(
+ `'done' received, but unexpected counts: expected ${expect_count} != actual ${count} (${e.data})`);
+ } else {
+ resolve(e.data);
+ }
+ } else {
+ reject("unexpected message received: " + e.data);
+ }
+ });
+ });
+ }
+
+ function checkSecurityPolicyViolationEvent(expect_count) {
+ return new Promise((resolve, reject) => {
+ let count = 0;
+ document.addEventListener("securitypolicyviolation", e => {
+ if (e.sample.includes("trigger")) {
+ if (expect_count && count != expect_count) {
+ reject(
+ `'trigger' received, but unexpected counts: expected ${expect_count} != actual ${count}`);
+ } else {
+ resolve();
+ }
+ } else {
+ count = count + 1;
+ }
+ });
+ try {
+ document.getElementById("trigger").text = "trigger fail";
+ } catch(e) { }
+ });
+ }
+
+ // Original report:
+ promise_test(t => {
+ // Setup: Create a <script> element with a <p> child.
+ let s = document.createElement("script");
+
+ // Sanity check: Element child content (<p>) doesn't count as source text.
+ let p = document.createElement("p");
+ p.text = "hello('world');";
+ s.appendChild(p);
+ container.appendChild(s);
+ assert_equals(s.text, "");
+
+ // Try to insertAdjacentText into the <script>, starting from the <p>
+ p.insertAdjacentText("beforebegin",
+ "postMessage('beforebegin should be blocked', '*');");
+ assert_true(s.text.includes("postMessage"));
+ p.insertAdjacentText("afterend",
+ "postMessage('afterend should be blocked', '*');");
+ assert_true(s.text.includes("after"));
+ return checkMessage();
+ }, "Regression test: Bypass via insertAdjacentText, initial comment.");
+
+ const script_elements = {
+ "script": doc => doc.createElement("script"),
+ "svg:script": doc => doc.createElementNS("http://www.w3.org/2000/svg", "script"),
+ };
+ for (let [element, create_element] of Object.entries(script_elements)) {
+ // Like the "Original Report" test case above, but avoids use of the "text"
+ // accessor that <svg:script> doesn't support.
+ promise_test(t => {
+ let s = create_element(document);
+
+ // Sanity check: Element child content (<p>) doesn't count as source text.
+ let p = document.createElement("p");
+ p.textContent = "hello('world');";
+ s.appendChild(p);
+ container.appendChild(s);
+
+ // Try to insertAdjacentText into the <script>, starting from the <p>
+ p.insertAdjacentText("beforebegin",
+ "postMessage('beforebegin should be blocked', '*');");
+ assert_true(s.textContent.includes("postMessage"));
+ p.insertAdjacentText("afterend",
+ "postMessage('afterend should be blocked', '*');");
+ assert_true(s.textContent.includes("after"));
+ return checkMessage();
+ }, "Regression test: Bypass via insertAdjacentText, initial comment. " + element);
+
+ // Variant: Create a <script> element and create & insert a text node. Then
+ // insert it into the document container to make it live.
+ promise_test(t => {
+ // Setup: Create a <script> element, and insert text via a text node.
+ let s = create_element(document);
+ let text = document.createTextNode("postMessage('appendChild with a " +
+ "text node should be blocked', '*');");
+ s.appendChild(text);
+ container.appendChild(s);
+ return checkMessage();
+ }, "Regression test: Bypass via appendChild into off-document script element" + element);
+
+ // Variant: Create a <script> element and insert it into the document. Then
+ // create a text node and insert it into the live <script> element.
+ promise_test(t => {
+ // Setup: Create a <script> element, insert it into the doc, and then create
+ // and insert text via a text node.
+ let s = create_element(document);
+ container.appendChild(s);
+ let text = document.createTextNode("postMessage('appendChild with a live " +
+ "text node should be blocked', '*');");
+ s.appendChild(text);
+ return checkMessage();
+ }, "Regression test: Bypass via appendChild into live script element " + element);
+ }
+
+ promise_test(t => {
+ return checkSecurityPolicyViolationEvent();
+ }, "Prep for subsequent tests: Clear SPV event queue.");
+
+ promise_test(t => {
+ const inserted_script = document.getElementById("script1");
+ assert_throws_js(TypeError, _ => {
+ inserted_script.innerHTML = "2+2";
+ });
+
+ let new_script = document.createElement("script");
+ assert_throws_js(TypeError, _ => {
+ new_script.innerHTML = "2+2";
+ container.appendChild(new_script);
+ });
+
+ const trusted_html = policy.createHTML("2*4");
+ assert_equals("" + trusted_html, "3*4");
+ inserted_script.innerHTML = trusted_html;
+ assert_equals(inserted_script.textContent, "3*4");
+
+ new_script = document.createElement("script");
+ new_script.innerHTML = trusted_html;
+ container.appendChild(new_script);
+ assert_equals(inserted_script.textContent, "3*4");
+
+ // We expect 3 SPV events: two for the two assert_throws_js cases, and one
+ // for script element, which will be rejected at the time of execution.
+ return checkSecurityPolicyViolationEvent(3);
+ }, "Spot tests around script + innerHTML interaction.");
+
+
+ // Create default policy. Wrapped in a promise_test to ensure it runs only
+ // after the other tests.
+ let default_policy;
+ promise_test(t => {
+ default_policy = trustedTypes.createPolicy("default", policy_dict);
+ return Promise.resolve();
+ }, "Prep for subsequent tests: Create default policy.");
+
+ for (let [element, create_element] of Object.entries(script_elements)) {
+ promise_test(t => {
+ let s = create_element(document);
+ let text = document.createTextNode("postMessage('default', '*');");
+ s.appendChild(text);
+ container.appendChild(s);
+ return Promise.all([checkMessage(1),
+ checkSecurityPolicyViolationEvent(0)]);
+ }, "Test that default policy applies. " + element);
+
+ promise_test(t => {
+ let s = create_element(document);
+ let text = document.createTextNode("fail");
+ s.appendChild(text);
+ container.appendChild(s);
+ return Promise.all([checkMessage(0),
+ checkSecurityPolicyViolationEvent(1)]);
+ }, "Test a failing default policy. " + element);
+ }
+
+ promise_test(t => {
+ const inserted_script = document.getElementById("script1");
+ inserted_script.innerHTML = "2+2";
+ assert_equals(inserted_script.textContent, "3+3");
+
+ let new_script = document.createElement("script");
+ new_script.innerHTML = "2+2";
+ container.appendChild(new_script);
+ assert_equals(inserted_script.textContent, "3+3");
+
+ const trusted_html = default_policy.createHTML("2*4");
+ assert_equals("" + trusted_html, "3*4");
+ inserted_script.innerHTML = trusted_html;
+ assert_equals(inserted_script.textContent, "3*4");
+
+ new_script = document.createElement("script");
+ new_script.innerHTML = trusted_html;
+ container.appendChild(new_script);
+ assert_equals(inserted_script.textContent, "3*4");
+
+ return checkSecurityPolicyViolationEvent(0);
+ }, "Spot tests around script + innerHTML interaction with default policy.");
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/trusted-types/csp-block-eval.tentative.html b/testing/web-platform/tests/trusted-types/csp-block-eval.tentative.html
new file mode 100644
index 0000000000..e3911bf9e6
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/csp-block-eval.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+
+ <!-- Note: Trusted Types enforcement, and a CSP that does not blanket-allow eval. -->
+ <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abc'; require-trusted-types-for 'script'">
+</head>
+<body>
+<script nonce="abc">
+ const p = createScript_policy(window, 1);
+
+ test(t => {
+ let a = 0;
+ assert_throws_js(EvalError, _ => {
+ eval('a="hello there"');
+ });
+ assert_equals(a, 0);
+ }, "eval with plain string throws (both block).");
+
+ test(t => {
+ let a = 0;
+ assert_throws_js(EvalError, _ => {
+ eval(p.createScript('a="Hello transformed string"'));
+ });
+ assert_equals(a, 0);
+ }, "eval with TrustedScript throws (script-src blocks).");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/default-policy-callback-arguments.tentative.html b/testing/web-platform/tests/trusted-types/default-policy-callback-arguments.tentative.html
new file mode 100644
index 0000000000..a4a9c9e351
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/default-policy-callback-arguments.tentative.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="require-trusted-types-for 'script'">
+</head>
+<body>
+ <div id="log"></div>
+ <div id="div"></div>
+ <script id="script"></script>
+ <script>
+ var current_case = undefined;
+ function checker(...args) {
+ assert_equals(args.length, 3);
+ assert_true(current_case && current_case.length == 4);
+ assert_equals(args[0], current_case[0], "Expecting the value.");
+ assert_equals(args[1], current_case[1], "Expecting the type name.");
+ assert_equals(args[2], current_case[2], "Expecting the sink name.");
+ return args[0];
+ }
+
+ trustedTypes.createPolicy("default", {
+ createHTML: checker,
+ createScript: checker,
+ createScriptURL: checker
+ });
+
+ const div = document.getElementById("div");
+ const script = document.getElementById("script");
+ const cases = [
+ [ "abc", "TrustedHTML", "Element innerHTML",
+ _ => div.innerHTML = "abc" ],
+ [ "2+2", "TrustedScript", "Node textContent",
+ _ => script.textContent = "2+2" ],
+ [ "about:blank", "TrustedScriptURL", "HTMLScriptElement src",
+ _ => script.src = "about:blank" ],
+ [ "2+2", "TrustedScript", "eval", _ => eval("2+2") ],
+ [ "(function anonymous(\n) {\nreturn 2+2\n})", "TrustedScript",
+ "Function", _ => new Function("return 2+2") ],
+ ];
+ for (var tc of cases) {
+ test(t => {
+ current_case = tc;
+ tc[3]();
+ }, `Test callback arguments, case ${tc[2]}`);
+ }
+ </script>
+</body>
+
diff --git a/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html b/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html
new file mode 100644
index 0000000000..1cff751a80
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<script>
+// Ensure that only the right events trigger violation reports.
+// The Promise will resolve, when an event including the string "done" is
+// received. The last line of this test file will cause this trigger.
+promise_test(t => {
+ let count = { "null": 0, "undefined": 0, "nodefault": 0 };
+ return new Promise((resolve, reject) => {
+ document.addEventListener("securitypolicyviolation", e => {
+ e.stopPropagation();
+ // We count the violation reports. We expect one each for "null" and
+ // "undefined", one each for the "no default" test case above, and one
+ // for the "done" line at the end, which signals the end of the test run.
+ if (e.sample.includes("done")) {
+ resolve(count);
+ } else if (e.sample.includes("null")) {
+ count["null"]++;
+ } else if (e.sample.includes("undefined")) {
+ count["undefined"]++;
+ } else if (e.sample.includes("nodefault")) {
+ count["nodefault"]++;
+ } else {
+ reject();
+ }
+ });
+ }).then(counters => {
+ for (const counter of ["null", "undefined", "nodefault"]) {
+ assert_equals(counters[counter], testCases.length,
+ "event count of " + counter);
+ }
+ });
+}, "Count SecurityPolicyViolation events.");
+
+const testCases = [
+ [ "script", "src" ],
+ [ "div", "innerHTML" ],
+ [ "script", "text" ],
+];
+
+// Try each test case _without_ a default policy.
+testCases.forEach(c => {
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "nodefault";
+ assert_true(element[c[1]].includes("nodefault"));
+ }, `${c[0]}.${c[1]} no default policy`);
+});
+
+// A trusted type policy that forces a number of edge cases.
+function policy(str) {
+ if (str == "throw")
+ throw RangeError();
+ else if (str == "null")
+ return null;
+ else if (str == "undefined")
+ return undefined;
+ else if (str == "typeerror")
+ return document.bla();
+ else if (str == "done")
+ return null;
+ else
+ return "sanitized: " + str;
+}
+
+trustedTypes.createPolicy("default", {
+ createScriptURL: policy,
+ createHTML: policy,
+ createScript: policy
+});
+
+testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "abc";
+ assert_equals(element[c[1]], "sanitized: abc");
+ }, name + "default");
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "null";
+ assert_true(element[c[1]].includes("null"));
+ }, name + "null");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(RangeError, _ => element[c[1]] = "throw");
+ }, name + "throw");
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "undefined";
+ assert_true(element[c[1]].includes("undefined"));
+ }, name + "undefined");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "typeerror");
+ }, name + "typeerror");
+});
+
+// Trigger the exit condition in the "Count" promise test above.
+try { document.createElement("script").text = "done"; } catch (e) {}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html.headers
new file mode 100644
index 0000000000..4c1ff15e16
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/default-policy-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/default-policy.tentative.html b/testing/web-platform/tests/trusted-types/default-policy.tentative.html
new file mode 100644
index 0000000000..debde85cda
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/default-policy.tentative.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support/helper.sub.js"></script>
+</head>
+<body>
+<script>
+// Ensure that only the right events trigger violation reports.
+// The Promise will resolve, when an event including the string "done" is
+// received. The last line of this test file will cause this trigger.
+promise_test(t => {
+ let count = { "null": 0, "undefined": 0, "nodefault": 0 };
+ return new Promise((resolve, reject) => {
+ document.addEventListener("securitypolicyviolation", e => {
+ e.stopPropagation();
+ // We count the violation reports. We expect one each for "null" and
+ // "undefined", one each for the "no default" test case above, and one
+ // for the "done" line at the end, which signals the end of the test run.
+ if (e.sample.includes("done")) {
+ resolve(count);
+ } else if (e.sample.includes("null")) {
+ count["null"]++;
+ } else if (e.sample.includes("undefined")) {
+ count["undefined"]++;
+ } else if (e.sample.includes("nodefault")) {
+ count["nodefault"]++;
+ } else {
+ reject();
+ }
+ });
+ }).then(counters => {
+ for (const counter of ["null", "undefined", "nodefault"]) {
+ assert_equals(counters[counter], testCases.length,
+ "event count of " + counter);
+ }
+ });
+}, "Count SecurityPolicyViolation events.");
+
+const testCases = [
+ [ "script", "src" ],
+ [ "div", "innerHTML" ],
+ [ "script", "text" ],
+];
+
+// Try each test case _without_ a default policy.
+testCases.forEach(c => {
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "nodefault");
+ assert_equals(element[c[1]], "");
+ }, `${c[0]}.${c[1]} no default policy`);
+});
+
+// A trusted type policy that forces a number of edge cases.
+function policy(str) {
+ if (str == "throw")
+ throw RangeError();
+ else if (str == "null")
+ return null;
+ else if (str == "undefined")
+ return undefined;
+ else if (str == "typeerror")
+ return document.bla();
+ else if (str == "done")
+ return null;
+ else
+ return "sanitized: " + str;
+}
+
+trustedTypes.createPolicy("default", {
+ createScriptURL: policy,
+ createHTML: policy,
+ createScript: policy
+});
+
+testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "abc";
+ assert_equals(element[c[1]], "sanitized: abc");
+ }, name + "default");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "null");
+ assert_equals(element[c[1]], "");
+ }, name + "null");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(RangeError, _ => element[c[1]] = "throw");
+ }, name + "throw");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "undefined");
+ assert_equals(element[c[1]], "");
+ }, name + "undefined");
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "typeerror");
+ }, name + "typeerror");
+});
+
+// Trigger the exit condition in the "Count" promise test above.
+try { document.createElement("script").text = "done"; } catch (e) {}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/default-policy.tentative.html.headers b/testing/web-platform/tests/trusted-types/default-policy.tentative.html.headers
new file mode 100644
index 0000000000..604e765da4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/default-policy.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html b/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html
new file mode 100644
index 0000000000..1ba9c5ec18
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+// Ensure that only the right events trigger violation reports.
+// The Promise will resolve, when an event including the string "done" is
+// received. The last line of this test file will cause this trigger.
+promise_test(t => {
+ let count = 0;
+ return new Promise((resolve, reject) => {
+ document.addEventListener("securitypolicyviolation", e => {
+ e.stopPropagation();
+ // We count the violation reports. We expect one each for "abc" test cases, and one
+ // for the "done" line at the end, which signals the end of the test run.
+ if (e.sample.includes("done")) {
+ resolve(count);
+ } else if (e.sample.includes("abc")) {
+ count++;
+ } else {
+ reject();
+ }
+ });
+ }).then(counter => {
+ assert_equals(counter, testCases.length, "event count");
+ });
+}, "Count SecurityPolicyViolation events.");
+
+const testCases = [
+ [ "script", "src" ],
+ [ "div", "innerHTML" ],
+ [ "script", "text" ],
+];
+
+trustedTypes.createPolicy("default", {});
+
+testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ const element = document.createElement(c[0]);
+ element[c[1]] = "abc";
+ if (c[1] == "src") {
+ assert_equals(element[c[1]], location.protocol + "//" + location.host + "/trusted-types/abc");
+ } else {
+ assert_equals(element[c[1]], "abc");
+ }
+ }, name + "default");
+});
+
+// Trigger the exit condition in the "Count" promise test above.
+try { document.createElement("script").text = "done"; } catch (e) {}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html.headers
new file mode 100644
index 0000000000..4c1ff15e16
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/empty-default-policy-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html b/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html
new file mode 100644
index 0000000000..d31b48ecd5
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+// Ensure that only the right events trigger violation reports.
+// The Promise will resolve, when an event including the string "done" is
+// received. The last line of this test file will cause this trigger.
+promise_test(t => {
+ let count = 0;
+ return new Promise((resolve, reject) => {
+ document.addEventListener("securitypolicyviolation", e => {
+ e.stopPropagation();
+ // We count the violation reports. We expect one each for "abc" test cases, and one
+ // for the "done" line at the end, which signals the end of the test run.
+ if (e.sample.includes("done")) {
+ resolve(count);
+ } else if (e.sample.includes("abc")) {
+ count++;
+ } else {
+ reject();
+ }
+ });
+ }).then(counter => {
+ assert_equals(counter, testCases.length, "event count");
+ });
+}, "Count SecurityPolicyViolation events.");
+
+const testCases = [
+ [ "script", "src" ],
+ [ "div", "innerHTML" ],
+ [ "script", "text" ],
+];
+
+trustedTypes.createPolicy("default", {});
+
+testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ const element = document.createElement(c[0]);
+ assert_throws_js(TypeError, _ => element[c[1]] = "abc");
+ assert_equals(element[c[1]], "");
+ }, name + "default");
+});
+
+// Trigger the exit condition in the "Count" promise test above.
+try { document.createElement("script").text = "done"; } catch (e) {}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html.headers b/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html.headers
new file mode 100644
index 0000000000..604e765da4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/empty-default-policy.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/eval-csp-no-tt.tentative.html b/testing/web-platform/tests/trusted-types/eval-csp-no-tt.tentative.html
new file mode 100644
index 0000000000..6720d80fe7
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-csp-no-tt.tentative.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-eval' 'nonce-abc'">
+</head>
+<body>
+<script nonce="abc">
+ const p = trustedTypes.createPolicy("p", {createScript: s => s});
+
+ test(t => {
+ assert_equals(eval(p.createScript("1+1")), 2);
+ }, "eval of TrustedScript works.");
+
+ test(t => {
+ assert_equals(eval('1+1'), 2);
+ }, "eval of string works.");
+
+ test(t => {
+ assert_equals(eval(42), 42);
+ assert_object_equals(eval({}), {});
+ assert_equals(eval(null), null);
+ assert_equals(eval(undefined), undefined);
+ }, "eval of !TrustedScript and !string works.");
+
+ test(t => {
+ assert_equals(new Function(p.createScript("return 1+1"))(), 2);
+ }, "Function constructor of TrustedScript works.");
+
+ test(t => {
+ assert_equals(new Function('return 1+1')(), 2);
+ }, "Function constructor of string works.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-csp-tt-default-policy.tentative.html b/testing/web-platform/tests/trusted-types/eval-csp-tt-default-policy.tentative.html
new file mode 100644
index 0000000000..9afe571199
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-csp-tt-default-policy.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+ trustedTypes.createPolicy("default", {createScript: s => s.replace("1", "4")});
+ const p = trustedTypes.createPolicy("p", {createScript: s => s});
+
+ test(t => {
+ assert_equals(eval(p.createScript('1+1')), 2);
+ }, "eval of TrustedScript works.");
+
+ test(t => {
+ assert_equals(eval('1+1'), 5); // '1+1' becomes '4+1'.
+ }, "eval of string works.");
+
+ test(t => {
+ assert_equals(eval(42), 42);
+ assert_object_equals(eval({}), {});
+ assert_equals(eval(null), null);
+ assert_equals(eval(undefined), undefined);
+ }, "eval of !TrustedScript and !string works.");
+
+ test(t => {
+ assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+ }, "Function constructor of TrustedScript works.");
+
+ test(t => {
+ assert_equals(new Function('return 1+1')(), 5);
+ }, "Function constructor of string works.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-csp-tt-no-default-policy.tentative.html b/testing/web-platform/tests/trusted-types/eval-csp-tt-no-default-policy.tentative.html
new file mode 100644
index 0000000000..8c4aba11ec
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-csp-tt-no-default-policy.tentative.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+</head>
+<body>
+<script>
+ const p = trustedTypes.createPolicy("p", {createScript: s => s});
+
+ test(t => {
+ assert_equals(eval(p.createScript('1+1')), 2);
+ }, "eval of TrustedScript works.");
+
+ test(t => {
+ assert_throws_js(EvalError, _ => eval('1+1'));
+ }, "eval of string fails.");
+
+ test(t => {
+ assert_equals(eval(42), 42);
+ assert_object_equals(eval({}), {});
+ assert_equals(eval(null), null);
+ assert_equals(eval(undefined), undefined);
+ }, "eval of !TrustedScript and !string works.");
+
+ test(t => {
+ assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+ }, "Function constructor of TrustedScript works.");
+
+ test(t => {
+ assert_throws_js(EvalError, _ => new Function('return 1+1')());
+ }, "Function constructor of string fails.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-function-constructor.tentative.html b/testing/web-platform/tests/trusted-types/eval-function-constructor.tentative.html
new file mode 100644
index 0000000000..a20bc4a78d
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-function-constructor.tentative.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+ let policy = trustedTypes.createPolicy("p", { createScript: s => s });
+ const args = ["a", "b", "c = 5", "return (a+b)*c;"];
+ const arg_max = 2 ** args.length -1;
+
+ // Call 'new Function(...args)', but with a subet of args being Strings,
+ // and a subset being TrustedScript. We use a bitmask to determine which
+ // argument gets to be trusted or not.
+ function new_function_with_maybe_trusted_args(mask) {
+ let maybe_trusted_args = args.map((value, arg_nr) => {
+ return (mask & (2**arg_nr)) ? policy.createScript(value) : value;
+ });
+ return new Function(...maybe_trusted_args);
+ }
+
+ // Generate all combinations of String/TrustedScript, except for the one
+ // where all argumentes are TrustedScript.
+ for (let mask = 0; mask < arg_max; mask++) {
+ test(t => {
+ assert_throws_js(EvalError,
+ _ => new_function_with_maybe_trusted_args(mask));
+ }, "Function constructor with mixed plain and trusted strings, mask #" + mask);
+ }
+
+ // Now do one with all trusted arguments.
+ test(t => {
+ const f = new_function_with_maybe_trusted_args(arg_max);
+ assert_equals(f(1,2,3), 9);
+ assert_equals(f(1,2), 15);
+ }, "Function constructor with mixed plain and trusted strings, mask #" + arg_max);
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html b/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html
new file mode 100644
index 0000000000..d36afbc8ac
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+ <!-- No CSP header. -->
+</head>
+<body>
+<script>
+ trustedTypes.createPolicy("default", {createScript: s => s + 4});
+ const p = trustedTypes.createPolicy("p", {createScript: s => s});
+
+ test(t => {
+ assert_equals(eval(p.createScript('1+1')), 2);
+ }, "eval of TrustedScript works.");
+
+ test(t => {
+ assert_equals(eval('1+1'), 2);
+ }, "eval of string works and does not call a default policy.");
+
+ test(t => {
+ assert_equals(eval(42), 42);
+ assert_object_equals(eval({}), {});
+ assert_equals(eval(null), null);
+ assert_equals(eval(undefined), undefined);
+ }, "eval of !TrustedScript and !string works.");
+
+ test(t => {
+ assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+ }, "Function constructor of TrustedScript works.");
+
+ test(t => {
+ assert_equals(new Function('return 1+1')(), 2);
+ }, "Function constructor of string works and does not call a default policy.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt.tentative.html b/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt.tentative.html
new file mode 100644
index 0000000000..3013c08447
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-no-csp-no-tt.tentative.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+ <!-- No CSP header. -->
+</head>
+<body>
+<script nonce="abc">
+ const p = trustedTypes.createPolicy("p", {createScript: s => s});
+
+ test(t => {
+ assert_equals(eval(p.createScript('1+1')), 2);
+ }, "eval of TrustedScript works.");
+
+ test(t => {
+ assert_equals(eval('1+1'), 2);
+ }, "eval of string works.");
+
+ test(t => {
+ assert_equals(eval(42), 42);
+ assert_object_equals(eval({}), {});
+ assert_equals(eval(null), null);
+ assert_equals(eval(undefined), undefined);
+ }, "eval of !TrustedScript and !string works.");
+
+ test(t => {
+ assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+ }, "Function constructor of TrustedScript works.");
+
+ test(t => {
+ assert_equals(new Function('return 1+1')(), 2);
+ }, "Function constructor of string works.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/eval-with-permissive-csp.tentative.html b/testing/web-platform/tests/trusted-types/eval-with-permissive-csp.tentative.html
new file mode 100644
index 0000000000..8910d4e7ef
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/eval-with-permissive-csp.tentative.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script nonce="abc" src="/resources/testharness.js"></script>
+ <script nonce="abc" src="/resources/testharnessreport.js"></script>
+ <script nonce="abc" src="support/helper.sub.js"></script>
+
+ <!-- Note: Trusted Types enforcement, and a CSP that allows all eval. -->
+ <meta http-equiv="Content-Security-Policy"
+ content="script-src 'nonce-abc' 'unsafe-eval'; require-trusted-types-for 'script'">
+</head>
+<body>
+<script nonce="abc">
+ let p = createScript_policy(window, 1);
+ test(t => {
+ let a = 0;
+ assert_throws_js(EvalError, _ => {
+ eval('a="hello there"');
+ });
+ assert_equals(a, 0);
+ }, "eval with plain string with Trusted Types and permissive CSP throws (no type).");
+
+ test(t => {
+ let a = 0;
+ assert_throws_js(EvalError, _ => {
+ new Function('a="hello there"');
+ });
+ assert_equals(a, 0);
+ }, "Function constructor with plain string with Trusted Types and permissive CSP throws (no type).");
+
+ test(t => {
+ let s = eval(p.createScript('"Hello transformed string"'));
+ assert_equals("" + s, "Hello a cat string");
+ }, "eval with TrustedScript and permissive CSP works.");
+
+ test(t => {
+ let s = new Function(p.createScript('return "Hello transformed string"'))();
+ assert_equals(s, "Hello a cat string");
+ }, "new Function with TrustedScript and permissive CSP works.");
+
+ trustedTypes.createPolicy("default", { createScript: createScriptJS }, true);
+ test(t => {
+ let s = eval('"Hello transformed untrusted string"');
+ assert_equals(s, "Hello a cat untrusted string");
+ }, "eval with default policy and permissive CSP still obeys default policy.");
+
+ test(t => {
+ let s = new Function('return "Hello transformed untrusted string"')();
+ assert_equals(s, "Hello a cat untrusted string");
+ }, "new Function with default policy and permissive CSP still obeys default policy.");
+</script>
+
diff --git a/testing/web-platform/tests/trusted-types/idlharness.tentative.window.js b/testing/web-platform/tests/trusted-types/idlharness.tentative.window.js
new file mode 100644
index 0000000000..07847fdb39
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/idlharness.tentative.window.js
@@ -0,0 +1,16 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+idl_test(
+ ['trusted-types'],
+ ['html', 'dom'],
+ idl_array => {
+ idl_array.add_objects({
+ TrustedTypePolicyFactory: ['window.trustedTypes'],
+ TrustedTypePolicy: ['window.trustedTypes.createPolicy("SomeName", { createHTML: s => s })'],
+ TrustedHTML: ['window.trustedTypes.createPolicy("SomeName1", { createHTML: s => s }).createHTML("A string")'],
+ TrustedScript: ['window.trustedTypes.createPolicy("SomeName2", { createScript: s => s }).createScript("A string")'],
+ TrustedScriptURL: ['window.trustedTypes.createPolicy("SomeName3", { createScriptURL: s => s }).createScriptURL("A string")'],
+ });
+ }
+);
diff --git a/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html
new file mode 100644
index 0000000000..651bf0a719
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ const testCases = [
+ ["script", "src"],
+ ["div", "innerHTML"],
+ ["script", "text"],
+ ];
+
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement(c[0]);
+ s[c[1]] = "https://example.com/";
+ assert_equals("https://example.com/", s[c[1]].toString());
+ }, name + "without trusted types");
+ });
+
+ p = trustedTypes.createPolicy("policyA",
+ {createScript: s => s + 1, createHTML: s => s + 1, createScriptURL: s => s + 1});
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement("script");
+ script = p.createScript("1");
+ s.innerText = script;
+ assert_equals(script.toString(), s.innerText.toString());
+ }, name + "with trusted types");
+ });
+
+ trustedTypes.createPolicy("default", {});
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement("script");
+ s.innerText = "1";
+ assert_equals(s.innerText.toString(), "1");
+ }, name + "empty default");
+ });
+</script>
diff --git a/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html.headers
new file mode 100644
index 0000000000..aa00fcc15a
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script'
diff --git a/testing/web-platform/tests/trusted-types/no-require-trusted-types-for.tentative.html b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for.tentative.html
new file mode 100644
index 0000000000..651bf0a719
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/no-require-trusted-types-for.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ const testCases = [
+ ["script", "src"],
+ ["div", "innerHTML"],
+ ["script", "text"],
+ ];
+
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement(c[0]);
+ s[c[1]] = "https://example.com/";
+ assert_equals("https://example.com/", s[c[1]].toString());
+ }, name + "without trusted types");
+ });
+
+ p = trustedTypes.createPolicy("policyA",
+ {createScript: s => s + 1, createHTML: s => s + 1, createScriptURL: s => s + 1});
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement("script");
+ script = p.createScript("1");
+ s.innerText = script;
+ assert_equals(script.toString(), s.innerText.toString());
+ }, name + "with trusted types");
+ });
+
+ trustedTypes.createPolicy("default", {});
+ testCases.forEach(c => {
+ const name = `${c[0]}.${c[1]} `;
+ test(t => {
+ s = document.createElement("script");
+ s.innerText = "1";
+ assert_equals(s.innerText.toString(), "1");
+ }, name + "empty default");
+ });
+</script>
diff --git a/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html b/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html
new file mode 100644
index 0000000000..25b4440ef4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = (filter_arg instanceof Function)
+ ? filter_arg(e)
+ : (e.originalPolicy.includes(filter_arg));
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+
+ d = document.createElement("div");
+ d.innerHTML = "a";
+ assert_equals("a", d.innerHTML);
+ return p;
+ }, "Require trusted types for 'script' block create HTML.");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+
+ d = document.createElement("script");
+ d.innerText = "a";
+ assert_equals("a", d.innerText);
+ return p;
+ }, "Require trusted types for 'script' block create script.");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+
+ s = document.createElement("script");
+ s.src = "a";
+ assert_true(s.src.includes("/trusted-types/a"));
+ return p;
+ }, "Require trusted types for 'script' block create script URL.");
+
+ promise_test(t => {
+ return new Promise(resolve => {
+ p = trustedTypes.createPolicy("policyA", {createScript: s => s+1});
+ p1 = trustedTypes.createPolicy("policyA", {createHTML: _ => ""});
+ p2 = trustedTypes.createPolicy("default", {});
+ script = p.createScript("1");
+ assert_equals(script.toString(), "11");
+ s = document.createElement("script");
+ s.innerText = script;
+ assert_equals(script.toString(), s.innerText.toString());
+ s.innerText = "1";
+ assert_equals("1", s.innerText);
+ resolve();
+ });
+ }, "Set require trusted types for 'script' without CSP for trusted types don't block policy creation and using.");
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html.headers
new file mode 100644
index 0000000000..c6412f8d47
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/require-trusted-types-for-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script' \ No newline at end of file
diff --git a/testing/web-platform/tests/trusted-types/require-trusted-types-for.tentative.html b/testing/web-platform/tests/trusted-types/require-trusted-types-for.tentative.html
new file mode 100644
index 0000000000..2a3820a89b
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/require-trusted-types-for.tentative.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = (filter_arg instanceof Function)
+ ? filter_arg(e)
+ : (e.originalPolicy.includes(filter_arg));
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+ d = document.createElement("div");
+ assert_throws_js(TypeError,
+ _ => {
+ d.innerHTML = "a";
+ });
+ assert_equals("", d.innerHTML);
+ return p;
+ }, "Require trusted types for 'script' block create HTML.");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+ d = document.createElement("script");
+ assert_throws_js(TypeError,
+ _ => {
+ d.innerText = "a";
+ });
+ assert_equals("", d.innerText);
+ return p;
+ }, "Require trusted types for 'script' block create script.");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"));
+ s = document.createElement("script");
+ assert_throws_js(TypeError,
+ _ => {
+ s.src = "a";
+ });
+ assert_equals("", s.src);
+ return p;
+ }, "Require trusted types for 'script' block create script URL.");
+
+ promise_test(t => {
+ return new Promise(resolve => {
+ p = trustedTypes.createPolicy("policyA", {createScript: s => s + 1});
+ p1 = trustedTypes.createPolicy("policyA", {createHTML: _ => ""});
+ p2 = trustedTypes.createPolicy("default", {createScript: s => s});
+ script = p.createScript("1");
+ assert_equals(script.toString(), "11");
+ s = document.createElement("script");
+ s.innerText = script;
+ assert_equals(script.toString(), s.innerText.toString());
+ s.innerText = "1";
+ assert_equals("1", s.innerText.toString());
+ resolve();
+ });
+ }, "Set require trusted types for 'script' without CSP for trusted types don't block policy creation and using.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.html b/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.html
new file mode 100644
index 0000000000..b9a0ceefae
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+<script>
+// Support script. This is meant to trigger deferred parsing. To accomplish this
+// we pad the file (with this very comment) to >>200B length, and then load it
+// with ...?pipe=tricle(200:d1) to ensure it's being delivered in pieces.
+window.parent.postMessage("first script element executed", "*");
+</script>
+<script>
+window.parent.postMessage("second script element executed", "*");
+</script>
+</head>
+<body>
+Hey!
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.js b/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.js
new file mode 100644
index 0000000000..7d574a6a13
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/HTMLScriptElement-internal-slot-support.js
@@ -0,0 +1,2 @@
+window.postMessage("script url", "*");
+
diff --git a/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js
new file mode 100644
index 0000000000..be0a4300e1
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js
@@ -0,0 +1,37 @@
+let test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", {
+ createScriptURL: x => x
+});
+importScripts(test_setup_policy.createScriptURL("/resources/testharness.js"));
+
+// Determine worker type (for better logging)
+let worker_type = "unknown";
+if (this.DedicatedWorkerGlobalScope !== undefined) {
+ worker_type = "dedicated worker";
+} else if (this.SharedWorkerGlobalScope !== undefined) {
+ worker_type = "shared worker";
+} else if (this.ServiceWorkerGlobalScope !== undefined) {
+ worker_type = "service worker";
+}
+
+// Test eval(string)
+test(t => {
+ assert_throws_js(EvalError, _ => eval("2"));
+}, "eval(string) in " + worker_type);
+
+// Test eval(TrustedScript)
+let test_policy = trustedTypes.createPolicy("xxx", {
+ createScript: x => x.replace("2", "7")
+});
+test(t => {
+ assert_equals(eval(test_policy.createScript("2")), 7);
+}, "eval(TrustedScript) in " + worker_type);
+
+// Test eval(String) with default policy
+trustedTypes.createPolicy("default", {
+ createScript: x => x.replace("2", "5")
+});
+test(t => {
+ assert_equals(eval("2"), 5);
+}, "eval(string) with default policy in " + worker_type);
+
+done();
diff --git a/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js.headers b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js.headers
new file mode 100644
index 0000000000..604e765da4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-eval.https.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js
new file mode 100644
index 0000000000..c40e8550dd
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js
@@ -0,0 +1,84 @@
+let test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", {
+ createScriptURL: x => x
+});
+importScripts(test_setup_policy.createScriptURL("/resources/testharness.js"));
+
+// Determine worker type (for better logging)
+let worker_type = "unknown";
+if (this.DedicatedWorkerGlobalScope !== undefined) {
+ worker_type = "dedicated worker";
+} else if (this.SharedWorkerGlobalScope !== undefined) {
+ worker_type = "shared worker";
+} else if (this.ServiceWorkerGlobalScope !== undefined) {
+ worker_type = "service worker";
+}
+
+let test_policy = trustedTypes.createPolicy("xxx", {
+ createScriptURL: url => url.replace("play", "work")
+});
+
+test(t => {
+ self.result = "Fail";
+ let trusted_url = test_policy.createScriptURL("player.js");
+ assert_true(this.trustedTypes.isScriptURL(trusted_url));
+ importScripts(trusted_url); // worker.js modifies self.result.
+ assert_equals(self.result, "Pass");
+}, "importScripts with TrustedScriptURL works in " + worker_type);
+
+test(t => {
+ let untrusted_url = "player.js";
+ assert_throws_js(TypeError,
+ function() { importScripts(untrusted_url) },
+ "importScripts(untrusted_url)");
+}, "importScripts with untrusted URLs throws in " + worker_type);
+
+test(t => {
+ assert_throws_js(TypeError,
+ function() { importScripts(null) },
+ "importScripts(null)");
+}, "null is not a trusted script URL throws in " + worker_type);
+
+test(t => {
+ self.result = "Fail";
+ let trusted_url = test_policy.createScriptURL("player.js?variant1");
+ let trusted_url2 = test_policy.createScriptURL("player.js?variant2");
+ importScripts(trusted_url, trusted_url2);
+ assert_equals(self.result, "Pass");
+}, "importScripts with two URLs, both trusted, in " + worker_type);
+
+test(t => {
+ let untrusted_url = "player.js?variant1";
+ let untrusted_url2 = "player.js?variant2";
+ assert_throws_js(TypeError,
+ function() { importScripts(untrusted_url, untrusted_url2) },
+ "importScripts(untrusted_url, untrusted_url2)");
+}, "importScripts with two URLs, both strings, in " + worker_type);
+
+test(t => {
+ let untrusted_url = "player.js";
+ let trusted_url = test_policy.createScriptURL(untrusted_url);
+ assert_throws_js(TypeError,
+ function() { importScripts(untrusted_url, trusted_url) },
+ "importScripts(untrusted_url, trusted_url)");
+}, "importScripts with two URLs, one trusted, in " + worker_type);
+
+// Test default policy application:
+trustedTypes.createPolicy("default", {
+ createScriptURL: url => url.replace("play", "work")
+}, true);
+test(t => {
+ self.result = "Fail";
+ let untrusted_url = "player.js";
+ importScripts(untrusted_url);
+ assert_equals(self.result, "Pass");
+}, "importScripts with untrusted URLs and default policy works in " + worker_type);
+
+test(t => {
+ self.result = "Fail";
+ let untrusted_url = "player.js";
+ let trusted_url = test_policy.createScriptURL(untrusted_url);
+ importScripts(untrusted_url, trusted_url);
+ assert_equals(self.result, "Pass");
+}, "importScripts with one trusted and one untrusted URLs and default policy works in " + worker_type);
+
+done();
diff --git a/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js.headers b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js.headers
new file mode 100644
index 0000000000..604e765da4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/WorkerGlobalScope-importScripts.https.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/support/frame-without-trusted-types.html b/testing/web-platform/tests/trusted-types/support/frame-without-trusted-types.html
new file mode 100644
index 0000000000..25cf073e79
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/frame-without-trusted-types.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/support/helper.sub.js b/testing/web-platform/tests/trusted-types/support/helper.sub.js
new file mode 100644
index 0000000000..2d1bd436bd
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/helper.sub.js
@@ -0,0 +1,166 @@
+const INPUTS = {
+ HTML: "Hi, I want to be transformed!",
+ SCRIPT: "Hi, I want to be transformed!",
+ SCRIPTURL: "http://this.is.a.scripturl.test/",
+};
+
+const RESULTS = {
+ HTML: "Quack, I want to be a duck!",
+ SCRIPT: "Meow, I want to be a cat!",
+ SCRIPTURL: "http://this.is.a.successful.test/",
+};
+
+function createHTMLJS(html) {
+ return html.replace("Hi", "Quack")
+ .replace("transformed", "a duck");
+}
+
+function createScriptJS(script) {
+ return script.replace("Hi", "Meow")
+ .replace("transformed", "a cat");
+}
+
+function createScriptURLJS(scripturl) {
+ return scripturl.replace("scripturl", "successful");
+}
+
+function createHTMLJSWithThreeArguments(html0, html1, html2) {
+ return html0 + html1 + html2;
+}
+
+function createScriptJSWithThreeArguments(script0, script1, script2) {
+ return script0 + script1 + script2;
+}
+
+function createScriptURLJSWithThreeArguments(scripturl0, scripturl1, scripturl2) {
+ return scripturl0 + scripturl1 + scripturl2;
+}
+
+function createHTML_policy(win, c) {
+ return win.trustedTypes.createPolicy('SomeHTMLPolicyName' + c, { createHTML: createHTMLJS });
+}
+
+function createScript_policy(win, c) {
+ return win.trustedTypes.createPolicy('SomeScriptPolicyName' + c, { createScript: createScriptJS });
+}
+
+function createScriptURL_policy(win, c) {
+ return win.trustedTypes.createPolicy('SomeScriptURLPolicyName' + c, { createScriptURL: createScriptURLJS });
+}
+
+function assert_element_accepts_trusted_html(win, c, t, tag, attribute, expected) {
+ let p = createHTML_policy(win, c);
+ let html = p.createHTML(INPUTS.HTML);
+ assert_element_accepts_trusted_type(tag, attribute, html, expected);
+}
+
+function assert_element_accepts_trusted_script(win, c, t, tag, attribute, expected) {
+ let p = createScript_policy(win, c);
+ let script = p.createScript(INPUTS.SCRIPT);
+ assert_element_accepts_trusted_type(tag, attribute, script, expected);
+}
+
+function assert_element_accepts_trusted_script_url(win, c, t, tag, attribute, expected) {
+ let p = createScriptURL_policy(win, c);
+ let scripturl = p.createScriptURL(INPUTS.SCRIPTURL);
+ assert_element_accepts_trusted_type(tag, attribute, scripturl, expected);
+}
+
+function assert_element_accepts_trusted_type(tag, attribute, value, expected) {
+ let elem = document.createElement(tag);
+ elem[attribute] = value;
+ assert_equals(elem[attribute] + "", expected);
+}
+
+function assert_throws_no_trusted_type(tag, attribute, value) {
+ let elem = document.createElement(tag);
+ let prev = elem[attribute];
+ assert_throws_js(TypeError, _ => {
+ elem[attribute] = value;
+ });
+ assert_equals(elem[attribute], prev);
+}
+
+function assert_element_accepts_trusted_html_explicit_set(win, c, t, tag, attribute, expected) {
+ let p = createHTML_policy(win, c);
+ let html = p.createHTML(INPUTS.HTML);
+ assert_element_accepts_trusted_type_explicit_set(tag, attribute, html, expected);
+}
+
+function assert_element_accepts_trusted_script_explicit_set(win, c, t, tag, attribute, expected) {
+ let p = createScript_policy(win, c);
+ let script = p.createScript(INPUTS.SCRIPT);
+ assert_element_accepts_trusted_type_explicit_set(tag, attribute, script, expected);
+}
+
+function assert_element_accepts_trusted_script_url_explicit_set(win, c, t, tag, attribute, expected) {
+ let p = createScriptURL_policy(win, c);
+ let scripturl = p.createScriptURL(INPUTS.SCRIPTURL);
+ assert_element_accepts_trusted_type_explicit_set(tag, attribute, scripturl, expected);
+}
+
+function assert_element_accepts_trusted_type_explicit_set(tag, attribute, value, expected) {
+ let elem = document.createElement(tag);
+ elem.setAttribute(attribute, value);
+ if (!/^on/.test(attribute)) { // "on" attributes are converted to functions.
+ assert_equals(elem[attribute] + "", expected);
+ }
+ assert_equals(elem.getAttribute(attribute), expected);
+}
+
+function assert_throws_no_trusted_type_explicit_set(tag, attribute, value) {
+ let elem = document.createElement(tag);
+ let prev = elem[attribute];
+ assert_throws_js(TypeError, _ => {
+ elem.setAttribute(attribute, value);
+ });
+ assert_equals(elem[attribute], prev);
+ assert_equals(elem.getAttribute(attribute), null);
+}
+
+function assert_element_accepts_non_trusted_type_explicit_set(tag, attribute, value, expected) {
+ let elem = document.createElement(tag);
+ elem.setAttribute(attribute, value);
+ assert_equals(elem[attribute] + "", expected);
+ assert_equals(elem.getAttribute(attribute), expected);
+}
+
+let namespace = 'http://www.w3.org/1999/xhtml';
+function assert_element_accepts_trusted_html_set_ns(win, c, t, tag, attribute, expected) {
+ let p = createHTML_policy(win, c);
+ let html = p.createHTML(INPUTS.HTML);
+ assert_element_accepts_trusted_type_set_ns(tag, attribute, html, expected);
+}
+
+function assert_element_accepts_trusted_script_set_ns(win, c, t, tag, attribute, expected) {
+ let p = createScript_policy(win, c);
+ let script = p.createScript(INPUTS.SCRIPT);
+ assert_element_accepts_trusted_type_set_ns(tag, attribute, script, expected);
+}
+
+function assert_element_accepts_trusted_script_url_set_ns(win, c, t, tag, attribute, expected) {
+ let p = createScriptURL_policy(win, c);
+ let scripturl = p.createScriptURL(INPUTS.SCRIPTURL);
+ assert_element_accepts_trusted_type_set_ns(tag, attribute, scripturl, expected);
+}
+
+function assert_element_accepts_trusted_type_set_ns(tag, attribute, value, expected) {
+ let elem = document.createElement(tag);
+ elem.setAttributeNS(namespace, attribute, value);
+ let attr_node = elem.getAttributeNodeNS(namespace, attribute);
+ assert_equals(attr_node.value + "", expected);
+}
+
+function assert_throws_no_trusted_type_set_ns(tag, attribute, value) {
+ let elem = document.createElement(tag);
+ assert_throws_js(TypeError, _ => {
+ elem.setAttributeNS(namespace, attribute, value);
+ });
+}
+
+function assert_element_accepts_non_trusted_type_set_ns(tag, attribute, value, expected) {
+ let elem = document.createElement(tag);
+ elem.setAttributeNS(namespace, attribute, value);
+ let attr_node = elem.getAttributeNodeNS(namespace, attribute);
+ assert_equals(attr_node.value + "", expected);
+}
diff --git a/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html b/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html
new file mode 100644
index 0000000000..5f7856fabb
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+<p>Support page for trusted-types-navigation-report-only.*.html tests.</p>
+<a id="anchor" href="#">link</a>
+<script>
+ const params = new URLSearchParams(location.search);
+ if (!!params.get("defaultpolicy")) {
+ trustedTypes.createPolicy("default", {
+ createScript: s => s.replace("continue", "defaultpolicywashere"),
+ });
+ }
+
+ function bounceEventToOpener(e) {
+ const msg = {};
+ for (const field of ["effectiveDirective", "sample", "type"]) {
+ msg[field] = e[field];
+ }
+ msg["uri"] = location.href;
+ window.opener.postMessage(msg, "*");
+ }
+
+ // If a navigation is blocked by Trusted Types, we expect this window to
+ // throw a SecurityPolicyViolationEvent. If it's not blocked, we expect the
+ // loaded frame to through DOMContentLoaded. In either case there should be
+ // _some_ event that we can expect.
+ document.addEventListener("DOMContentLoaded", bounceEventToOpener);
+ document.addEventListener("securitypolicyviolation", bounceEventToOpener);
+
+ // Navigate to the non-report-only version of the test. That has the same
+ // event listening setup as this, but is a different target URI.
+ const target_script = `location.href='${location.href.replace("-report-only", "") + "#continue"}';`;
+ const target = `javascript:"<script>${target_script}</scri${""}pt>"`;
+
+ // Navigate the anchor, but only after the content is loaded (so that we
+ // won't disturb delivery of that event to the opener.
+ const anchor = document.getElementById("anchor");
+ anchor.href = target;
+
+ if (!!params.get("frame")) {
+ const frame = document.createElement("iframe");
+ frame.src = "frame-without-trusted-types.html";
+ frames.name = "frame";
+ document.body.appendChild(frame);
+ anchor.target = "frame";
+ }
+
+ if (!location.hash) {
+ document.addEventListener("DOMContentLoaded", _ => anchor.click());
+ }
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html.headers b/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html.headers
new file mode 100644
index 0000000000..4c1ff15e16
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/navigation-report-only-support.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/support/navigation-support.html b/testing/web-platform/tests/trusted-types/support/navigation-support.html
new file mode 100644
index 0000000000..5e02e6d4bf
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/navigation-support.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+<p>Support page for trusted-types-navigation.*.html tests.</p>
+<a id="anchor" href="#">link</a>
+<script>
+ const params = new URLSearchParams(location.search);
+ if (!!params.get("defaultpolicy")) {
+ trustedTypes.createPolicy("default", {
+ createScript: s => s.replace("continue", "defaultpolicywashere"),
+ });
+ }
+
+ function bounceEventToOpener(e) {
+ const msg = {};
+ for (const field of ["effectiveDirective", "sample", "type"]) {
+ msg[field] = e[field];
+ }
+ msg["uri"] = location.href;
+ window.opener.postMessage(msg, "*");
+ }
+
+ // If a navigation is blocked by Trusted Types, we expect this window to
+ // throw a SecurityPolicyViolationEvent. If it's not blocked, we expect the
+ // loaded frame to through DOMContentLoaded. In either case there should be
+ // _some_ event that we can expect.
+ document.addEventListener("DOMContentLoaded", bounceEventToOpener);
+ document.addEventListener("securitypolicyviolation", bounceEventToOpener);
+
+ // We'll use a javascript:-url to navigate to ourselves, so that we can
+ // re-use the messageing mechanisms above. In order to not end up in a loop,
+ // we'll only click if we don't find fragment in the current URL.
+ const target_script = `location.href='${location.href}&continue';`;
+ const target = `javascript:"<script>${target_script}</scri${""}pt>"`;
+
+ const anchor = document.getElementById("anchor");
+ anchor.href = target;
+
+ if (!!params.get("frame")) {
+ const frame = document.createElement("iframe");
+ frame.src = "frame-without-trusted-types.html";
+ frames.name = "frame";
+ document.body.appendChild(frame);
+ anchor.target = "frame";
+ }
+
+ if (!location.hash)
+ document.addEventListener("DOMContentLoaded", _ => anchor.click());
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/support/navigation-support.html.headers b/testing/web-platform/tests/trusted-types/support/navigation-support.html.headers
new file mode 100644
index 0000000000..604e765da4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/navigation-support.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/support/set-inner-html.js b/testing/web-platform/tests/trusted-types/support/set-inner-html.js
new file mode 100644
index 0000000000..45053d43e3
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/set-inner-html.js
@@ -0,0 +1,3 @@
+function setInnerHtml(element, value) {
+ element.innerHTML = value;
+}
diff --git a/testing/web-platform/tests/trusted-types/support/worker.js b/testing/web-platform/tests/trusted-types/support/worker.js
new file mode 100644
index 0000000000..4079f7e9c7
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/support/worker.js
@@ -0,0 +1 @@
+self.result = "Pass";
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-createHTMLDocument.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-createHTMLDocument.tentative.html
new file mode 100644
index 0000000000..e4af2eb590
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-createHTMLDocument.tentative.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="trusted-types policy default 'allow-duplicates'; require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+
+// Test Trusted Types in document types other than the main document, such as
+// documents created by createHTMLDocument or XHR requests.
+
+function create_XHR_document() {
+ return new Promise(resolve => {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = _ => { resolve(xhr.response); };
+ xhr.open("GET", 'data:text/html,<title>aaa</title>');
+ xhr.responseType = "document";
+ xhr.send();
+ });
+}
+
+const doc_types = {
+ "document": _ => document,
+ "createHTMLDocument": _ => document.implementation.createHTMLDocument(""),
+ "DOMParser": _ => (new DOMParser).parseFromString(trustedTypes.emptyHTML, "text/html"),
+ "XHR": create_XHR_document,
+}
+
+function doc_test(doc_type, test_fn, description) {
+ promise_test(t => {
+ return Promise.resolve(doc_types[doc_type]()).then(test_fn);
+ }, `${description} (${doc_type})`);
+}
+
+for (let doc_type in doc_types) {
+ doc_test(doc_type, doc => {
+ assert_throws_js(TypeError,
+ _ => { doc.createElement("script").textContent = "2+2"; });
+ }, "Trusted Type assignment is blocked." );
+
+ doc_test(doc_type, doc => {
+ const policy = trustedTypes.createPolicy("policy", {createHTML: x => x });
+ const value = policy.createHTML("hello");
+ doc.body.innerHTML = value;
+ assert_equals(doc.body.textContent, "hello");
+ assert_throws_js(TypeError,
+ _ => { doc.body.innerHTML = "world"; });
+ }, "Trusted Type instances created in the main doc can be used.");
+}
+
+// Create default policy (applies to all subsequent tests).
+// Wrapped in a promise_test so that it won't interfere with the previous tests
+// (which hanve't yet run).
+promise_test(t => {
+ return new Promise(resolve => {
+ trustedTypes.createPolicy("default",
+ { createHTML: s => s + " [default]" });
+ resolve();
+ });
+}, "Install default policy.")
+
+for (let doc_type in doc_types) {
+ doc_test(doc_type, doc => {
+ doc.body.innerHTML = "shouldpass";
+ assert_equals(doc.body.textContent, "shouldpass [default]");
+ }, "Default policy applies.");
+}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html
new file mode 100644
index 0000000000..46ca2edb6f
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+// We assume the following header has been set:
+// Content-Security-Policy-Report-Only: trusted-types a b c
+// (CSP-Report-Only headers can't be set in <meta> tags.)
+
+test(t => {
+ trustedTypes.createPolicy("a", {});
+ trustedTypes.createPolicy("a", {});
+ trustedTypes.createPolicy("b", {});
+ trustedTypes.createPolicy("d", {});
+}, "TrustedTypePolicyFactory and policy list in CSP.");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html.headers
new file mode 100644
index 0000000000..b6608515aa
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: trusted-types a b c
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list.tentative.html
new file mode 100644
index 0000000000..afb2f5f7c4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-list.tentative.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="trusted-types a b c*">
+</head>
+<body>
+<script>
+test(t => {
+ trustedTypes.createPolicy("a", {}),
+ assert_throws_js(TypeError,
+ _ => trustedTypes.createPolicy("a", {}),
+ "Duplicate name");
+
+ trustedTypes.createPolicy("b", {}),
+
+ assert_throws_js(TypeError,
+ _ => trustedTypes.createPolicy("d", {}),
+ "Invalid name.");
+}, "TrustedTypePolicyFactory and policy list in CSP.");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-without-enforcement.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-without-enforcement.tentative.html
new file mode 100644
index 0000000000..afef457a9c
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names-without-enforcement.tentative.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+const policy = { createHTML: a => a };
+
+test(t => {
+ // The spec demands that duplicate policies are allowed when TT is not
+ // enforced in the CSP.
+ let a = trustedTypes.createPolicy("duplicatename", policy);
+ let b = trustedTypes.createPolicy("duplicatename", policy);
+ assert_not_equals(a, b);
+ assert_true(a instanceof TrustedTypePolicy);
+ assert_true(b instanceof TrustedTypePolicy);
+}, "createPolicy - duplicate policies are allowed when Trusted Types are not enforced.");
+
+test(t => {
+ // The spec demands that duplicate "default" policy creation fails, even
+ // when TT is not enforced.
+ let p = trustedTypes.createPolicy("default", policy);
+ assert_true(p instanceof TrustedTypePolicy);
+
+ // The second instance should throw:
+ assert_throws_js(TypeError, _ => trustedTypes.createPolicy("default", policy));
+}, "createPolicy - duplicate \"default\" policy is never allowed.");
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names.tentative.html
new file mode 100644
index 0000000000..decce53564
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-duplicate-names.tentative.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="trusted-types 'allow-duplicates' duplicatename default">
+</head>
+<body>
+<script>
+test(t => {
+ // We expect neither of these to throw.
+ let a = trustedTypes.createPolicy("duplicatename", { createHTML: _ => "a" });
+ let b = trustedTypes.createPolicy("duplicatename", { createHTML: _ => "b" });
+
+ // Both should have worked. They should still be separate functions.
+ assert_not_equals(a, b);
+ assert_equals("" + a.createHTML(""), "a");
+ assert_equals("" + b.createHTML(""), "b");
+
+ let def = trustedTypes.createPolicy("default", {});
+ assert_throws_js(TypeError,
+ _ => trustedTypes.createPolicy("default", {}));
+}, "policy - duplicate names");
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html
new file mode 100644
index 0000000000..2b0922d212
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<head>
+ <script nonce="123" src="/resources/testharness.js"></script>
+ <script nonce="123"src="/resources/testharnessreport.js"></script>
+ <script nonce="123"src="/content-security-policy/support/testharness-helper.js"></script>
+</head>
+<body>
+ <script nonce="123">
+ // CSP insists the "trusted-types: ..." directives are deliverd as headers
+ // (rather than as "<meta http-equiv" tags). This test assumes the following
+ // headers are set in the .headers file:
+ //
+ // Content-Security-Policy: script-src 'unsafe-inline'; report-uri ...
+ // Content-Security-Policy: object-src 'none'
+ // Content-Security-Policy: require-trusted-types-for 'script'
+ //
+ // The second rule is there so we can provoke a CSP violation report at will.
+ // The intent is that in order to test that a violation has *not* been thrown
+ // (and without resorting to abominations like timeouts), we force a *another*
+ // CSP violation (by violating the object-src rule) and when that event is
+ // processed we can we sure that an earlier event - if it indeed occurred -
+ // must have already been processed.
+
+ // Return function that returns a promise that resolves on the given
+ // violation report.
+ // how_many - how many violation events are expected.
+ // filter_arg - iff function, call it with the event object.
+ // Else, string-ify and compare against event.originalPolicy.
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = (filter_arg instanceof Function)
+ ? filter_arg(e)
+ : (e.originalPolicy.includes(filter_arg));
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ // Like assert_throws_*, but we don't care about the exact error. We just want
+ // to run the code and continue.
+ function expect_throws(fn) {
+ try { fn(); assert_unreached(); } catch (err) { /* ignore */ }
+ }
+
+ // A sample policy we use to test trustedTypes.createPolicy behaviour.
+ const id = x => x;
+ const a_policy = {
+ createHTML: id,
+ createScriptURL: id,
+ createURL: id,
+ createScript: id,
+ };
+
+ const scriptyPolicy = trustedTypes.createPolicy('allowEval', a_policy);
+
+ // Provoke/wait for a CSP violation, in order to be sure that all previous
+ // CSP violations have been delivered.
+ function promise_flush() {
+ return promise_violation("object-src 'none'");
+ }
+ function flush() {
+ expect_throws(_ => {
+ var o = document.createElement('object');
+ o.type = "application/x-shockwave-flash";
+ document.body.appendChild(o);
+ });
+ }
+
+ window.script_run_beacon = 'never_overwritten';
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(promise_flush());
+ expect_throws(_ => eval('script_run_beacon="should not run"'));
+ assert_equals(script_run_beacon, 'never_overwritten');
+ flush();
+ return p;
+ }, "Trusted Type violation report: evaluating a string violates both script-src and trusted-types.");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("script-src"))
+ .then(promise_flush());
+ expect_throws(_ => eval(scriptyPolicy.createScript('script_run_beacon="i ran"')));
+ flush();
+ assert_not_equals(script_run_beacon, 'i ran'); // Code did not run.
+ return p;
+ }, "Trusted Type violation report: evaluating a Trusted Script violates script-src.");
+
+ promise_test(t => {
+ trustedTypes.createPolicy('default', {
+ createScript: s => s.replace('payload', 'default policy'),
+ }, true);
+ let p = Promise.resolve()
+ .then(promise_violation((e) =>
+ e.effectiveDirective.includes('script-src') &&
+ e.sample.includes("default policy")))
+ .then(promise_flush());
+ expect_throws(_ => eval('script_run_beacon="payload"')); // script-src will block.
+ assert_not_equals(script_run_beacon, 'default policy'); // Code did not run.
+ flush();
+ return p;
+ }, "Trusted Type violation report: script-src restrictions apply after the default policy runs.");
+
+ </script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html.headers
new file mode 100644
index 0000000000..2bdd8a7d1a
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-no-unsafe-eval.tentative.html.headers
@@ -0,0 +1,3 @@
+Content-Security-Policy: script-src http: https: 'nonce-123' 'report-sample'
+Content-Security-Policy: object-src 'none'
+Content-Security-Policy: require-trusted-types-for 'script'
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html
new file mode 100644
index 0000000000..4e8ac5a2f4
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<head>
+ <script nonce="123" src="/resources/testharness.js"></script>
+ <script nonce="123"src="/resources/testharnessreport.js"></script>
+ <script nonce="123"src="/content-security-policy/support/testharness-helper.js"></script>
+</head>
+<body>
+ <script nonce="123">
+ // CSP insists the "trusted-types: ..." directives are deliverd as headers
+ // (rather than as "<meta http-equiv" tags). This test assumes the following
+ // headers are set in the .headers file:
+ //
+ // Content-Security-Policy: script-src 'unsafe-inline' 'unsafe-eval'; report-uri ...
+ // Content-Security-Policy: object-src 'none'
+ // Content-Security-Policy-Report-Only: require-trusted-types-for 'script'
+ //
+ // The last rule is there so we can provoke a CSP violation report at will.
+ // The intent is that in order to test that a violation has *not* been thrown
+ // (and without resorting to abominations like timeouts), we force a *another*
+ // CSP violation (by violating the img-src rule) and when that event is
+ // processed we can we sure that an earlier event - if it indeed occurred -
+ // must have already been processed.
+
+ // Return function that returns a promise that resolves on the given
+ // violation report.
+ //
+ // filter_arg - iff function, call it with the event object.
+ // Else, string-ify and compare against event.originalPolicy.
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = (filter_arg instanceof Function)
+ ? filter_arg(e)
+ : (e.originalPolicy.includes(filter_arg));
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ // Like assert_throws_*, but we don't care about the exact error. We just want
+ // to run the code and continue.
+ function expect_throws(fn) {
+ try { fn(); assert_unreached(); } catch (err) { /* ignore */ }
+ }
+
+ // A sample policy we use to test trustedTypes.createPolicy behaviour.
+ const id = x => x;
+ const a_policy = {
+ createHTML: id,
+ createScriptURL: id,
+ createURL: id,
+ createScript: id,
+ };
+
+ const scriptyPolicy = trustedTypes.createPolicy('allowEval', a_policy);
+
+ // Provoke/wait for a CSP violation, in order to be sure that all previous
+ // CSP violations have been delivered.
+ function promise_flush() {
+ return promise_violation("object-src 'none'");
+ }
+ function flush() {
+ expect_throws(_ => {
+ var o = document.createElement('object');
+ o.type = "application/x-shockwave-flash";
+ document.body.appendChild(o);
+ });
+ }
+
+ window.script_run_beacon = 'vanilla';
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(promise_flush());
+ eval('script_run_beacon="report-only-does-not-stop"');
+ assert_equals(script_run_beacon, 'report-only-does-not-stop');
+ flush();
+ return p;
+ }, "Trusted Type violation report: evaluating a string.");
+
+ promise_test(t => {
+ let p = promise_flush()();
+ eval(scriptyPolicy.createScript('script_run_beacon="trusted-script-ok"'));
+ flush();
+ assert_equals(script_run_beacon, 'trusted-script-ok');
+ return p;
+ }, "Trusted Type violation report: evaluating a Trusted Script.");
+
+ promise_test(t => {
+ trustedTypes.createPolicy('default', {
+ createScript: s => s.replace('payload', 'default policy'),
+ }, true);
+ let p = promise_flush()();
+ eval('script_run_beacon="payload"');
+ assert_equals(script_run_beacon, 'default policy');
+ flush();
+ return p;
+ }, "Trusted Type violation report: default policy runs in report-only mode.");
+
+ </script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html.headers
new file mode 100644
index 0000000000..d212eda5ef
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting-report-only.tentative.html.headers
@@ -0,0 +1,4 @@
+Content-Security-Policy: script-src http: https: 'nonce-123' 'unsafe-eval'
+Content-Security-Policy: object-src 'none'
+Content-Security-Policy-Report-Only: require-trusted-types-for 'script'
+
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html
new file mode 100644
index 0000000000..73bb011349
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<head>
+ <script nonce="123" src="/resources/testharness.js"></script>
+ <script nonce="123" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script nonce="123">
+ // CSP insists the "trusted-types: ..." directives are deliverd as headers
+ // (rather than as "<meta http-equiv" tags). This test assumes the following
+ // headers are set in the .headers file:
+ //
+ // Content-Security-Policy: script-src 'unsafe-inline' 'unsafe-eval'; report-uri ...
+ // Content-Security-Policy: object-src 'none'
+ // Content-Security-Policy: require-trusted-types-for 'script'
+ //
+ // The last rule is there so we can provoke a CSP violation report at will.
+ // The intent is that in order to test that a violation has *not* been thrown
+ // (and without resorting to abominations like timeouts), we force a *another*
+ // CSP violation (by violating the img-src rule) and when that event is
+ // processed we can we sure that an earlier event - if it indeed occurred -
+ // must have already been processed.
+
+ // Return function that returns a promise that resolves on the given
+ // violation report.
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = e.originalPolicy.includes(filter_arg);
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ // Like assert_throws_*, but we don't care about the exact error. We just want
+ // to run the code and continue.
+ function expect_throws(fn) {
+ try { fn(); assert_unreached(); } catch (err) { /* ignore */ }
+ }
+
+ // A sample policy we use to test trustedTypes.createPolicy behaviour.
+ const id = x => x;
+ const a_policy = {
+ createHTML: id,
+ createScriptURL: id,
+ createURL: id,
+ createScript: id,
+ };
+ const scriptyPolicy = trustedTypes.createPolicy('allowEval', a_policy);
+
+ // Provoke/wait for a CSP violation, in order to be sure that all previous
+ // CSP violations have been delivered.
+ function promise_flush() {
+ return promise_violation("object-src 'none'");
+ }
+ function flush() {
+ expect_throws(_ => {
+ var o = document.createElement('object');
+ o.type = "application/x-shockwave-flash";
+ document.body.appendChild(o);
+ });
+ }
+
+ promise_test(t => {
+ let beacon = 'never_overwritten';
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(promise_flush());
+ assert_throws_js(EvalError,
+ _ => eval('beacon="should not run"'));
+ assert_equals(beacon, 'never_overwritten');
+ flush();
+ return p;
+ }, "Trusted Type violation report: evaluating a string.");
+
+ promise_test(t => {
+ let beacon = 'never_overwritten2';
+ let p = promise_flush()();
+ eval(scriptyPolicy.createScript('beacon="i ran"'));
+ assert_equals(beacon, 'i ran');
+ flush();
+ return p;
+ }, "Trusted Type violation report: evaluating a Trusted Script.");
+
+ promise_test(t => {
+ let beacon = 'never_overwritten';
+ trustedTypes.createPolicy('default', {
+ createScript: s => s.replace('payload', 'default policy'),
+ }, true);
+ let p = promise_flush()();
+ eval('beacon="payload"');
+ assert_equals(beacon, 'default policy');
+ flush();
+ return p;
+ }, "Trusted Type violation report: default policy transforms the script before CSP checks runs.");
+
+ </script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html.headers
new file mode 100644
index 0000000000..8989345e72
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-eval-reporting.tentative.html.headers
@@ -0,0 +1,4 @@
+Content-Security-Policy: script-src http: https: 'nonce-123' 'unsafe-eval'
+Content-Security-Policy: object-src 'none'
+Content-Security-Policy: require-trusted-types-for 'script'
+
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-event-handlers.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-event-handlers.tentative.html
new file mode 100644
index 0000000000..57f8d3d90c
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-event-handlers.tentative.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+const element = document.createElement("div");
+
+[
+ "onclick",
+ "onchange",
+ "onfocus",
+ "oNclick",
+ "OnClIcK"
+].forEach(name => {
+ test(t => {
+ assert_throws_js(TypeError,
+ _ => element.setAttribute(name, "2+2"));
+ }, `Event handler ${name} should be blocked.`);
+});
+
+[
+ "one",
+ "oNe",
+ "onIcon",
+ "offIcon",
+ "blubb"
+].forEach(name => {
+ test(t => {
+ element.setAttribute(name, "2+2");
+ }, `Non-event handler ${name} should not be blocked.`);
+});
+
+// We'd like to be sure we're not missing anything. Let's "query" an HTML
+// element about which attributes it knows.
+const div = document.createElement("div");
+for(name in div.__proto__) {
+ const should_be_event_handler = name.startsWith("on");
+ if (should_be_event_handler) {
+ test(t => {
+ assert_throws_js(TypeError,
+ _ => element.setAttribute(name, "2+2"));
+ }, `Event handler div.${name} should be blocked.`);
+ } else {
+ test(t => {
+ element.setAttribute(name, "2+2");
+ }, `Non-event handler div.${name} should not be blocked.`);
+ }
+}
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-from-literal.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-from-literal.tentative.html
new file mode 100644
index 0000000000..a7d5659e16
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-from-literal.tentative.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<head>
+<link rel="author" title="Daniel Vogelheim" href="mailto:vogelheim@chromium.org"></link>
+<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/"></link>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+[ TrustedHTML, TrustedScript, TrustedScriptURL ].forEach(type => {
+
+ test(t => {
+ assert_true("fromLiteral" in type);
+ }, `${type.name}.fromLiteral is supported`);
+
+ test(t => {
+ const c = type.fromLiteral`abc`;
+ assert_true(c instanceof type);
+ assert_equals(c.toString(), "abc");
+ }, `${type.name}.fromLiteral: Basic string literal works.`);
+
+ test(t => {
+ const c = type.fromLiteral``;
+ assert_true(c instanceof type);
+ assert_equals(c.toString(), "");
+ }, `${type.name}.fromLiteral: Empty string literal works.`);
+
+ test(t => {
+ const c = type.fromLiteral`\u{1f4a9}`;
+ assert_true(c instanceof type);
+ assert_equals(c.toString(), "\u{1f4a9}");
+ }, `${type.name}.fromLiteral: A very important emoji works.`);
+
+ test(t => {
+ const c = type.fromLiteral`A Multiline
+ string
+ works.`;
+ assert_true(c instanceof type);
+ assert_true(c.toString().includes("\n"));
+ }, `${type.name}.fromLiteral: Multi-line string literal works.`);
+
+ test(t => {
+ const tag = type.fromLiteral.bind(type);
+ const c = tag`abc`;
+ assert_true(c instanceof type);
+ assert_equals(c.toString(), "abc");
+ }, `${type.name}.fromLiteral: Bound method works.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral("abc");
+ });
+ }, `${type.name}.fromLiteral: String throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral(null);
+ });
+ }, `${type.name}.fromLiteral: null throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral(undefined);
+ });
+ }, `${type.name}.fromLiteral: undefined throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral({});
+ });
+ }, `${type.name}.fromLiteral: Object throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral`Hello ${2+3} world`
+ });
+ }, `${type.name}.fromLiteral: template literal with expression throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral(["abc"]);
+ });
+ }, `${type.name}.fromLiteral: non-literal throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral(Object.freeze(["abc"]));
+ });
+ }, `${type.name}.fromLiteral: frozen non-literal throws.`);
+
+ test(t => {
+ assert_throws_js(TypeError, _ => {
+ type.fromLiteral(["abc", "def"], "xxx");
+ });
+ }, `${type.name}.fromLiteral: non-literal with param throws.`);
+
+});
+
+// TrustedHTML requires normalization of the value. Let's test that TrustedHTML
+// (and only TrustedHTML) does this.
+test(t => {
+ const tag = TrustedHTML.fromLiteral.bind(TrustedHTML);
+ assert_equals(tag`<b>`.toString(), "<b></b>");
+}, "TrustedHTML.fromLiteral: Normalization of value works.");
+
+test(t => {
+ const tag = TrustedScript.fromLiteral.bind(TrustedScript);
+ assert_equals(tag`<b>`.toString(), "<b>");
+}, "TrustedScript.fromLiteral: No normalization of value occurs.");
+
+test(t => {
+ const tag = TrustedScriptURL.fromLiteral.bind(TrustedScriptURL);
+ assert_equals(tag`<b>`.toString(), "<b>");
+}, "TrustedScriptURL.fromLiteral: No normalization of value occurs.");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-navigation.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-navigation.tentative.html
new file mode 100644
index 0000000000..2113711902
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-navigation.tentative.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ function expectMessage(filter) {
+ return new Promise(resolve => {
+ window.addEventListener("message", e => { if (filter(e)) resolve(); });
+ });
+ }
+
+ function expectViolationAsMessage(sample) {
+ const filter = e => ((e.data.effectiveDirective == "require-trusted-types-for" ||
+ e.data.effectiveDirective == "trusted-types") &&
+ (!sample || e.data.sample.startsWith(sample)));
+ return new expectMessage(filter);
+ }
+
+ function expectLoadedAsMessage(uri) {
+ const filter = e => (e.data.type == "DOMContentLoaded" &&
+ (!uri || e.data.uri.endsWith(uri)));
+ return new expectMessage(filter);
+ }
+
+ function openWindow(test, uri) {
+ const win = window.open(uri);
+ test.add_cleanup(_ => win.close());
+ }
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html"),
+ expectViolationAsMessage("Location href"),
+ ]);
+ }, "Navigate a window with javascript:-urls in enforcing mode.");
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&defaultpolicywashere"),
+ ]);
+ }, "Navigate a window with javascript:-urls w/ default policy in enforcing mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html"
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html#continue"),
+ ]);
+ }, "Navigate a window with javascript:-urls in report-only mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html?defaultpolicy=1";
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1#defaultpolicywashere"),
+ ]);
+ }, "Navigate a window with javascript:-urls w/ default policy in report-only mode.");
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html?frame=1");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html?frame=1"),
+ expectViolationAsMessage("Location href"),
+ ]);
+ }, "Navigate a frame with javascript:-urls in enforcing mode.");
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1&frame=1");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1&defaultpolicywashere"),
+ ]);
+ }, "Navigate a frame with javascript:-urls w/ default policy in enforcing mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html?frame=1"
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html?frame=1#continue"),
+ ]);
+ }, "Navigate a frame with javascript:-urls in report-only mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html?defaultpolicy=1&frame=1";
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1#defaultpolicywashere"),
+ ]);
+ }, "Navigate a frame with javascript:-urls w/ default policy in report-only mode.");
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html
new file mode 100644
index 0000000000..fcb7784116
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/content-security-policy/support/testharness-helper.js"></script>
+</head>
+<body>
+
+ <!-- Some elements for the tests to act on. -->
+ <div id="div"></div>
+ <script id="script-src" src=""></script>
+ <script id="script"></script>
+ <script id="script2"></script>
+
+ <script>
+ // CSP insists the "trusted-types: ..." directives are deliverd as headers
+ // (rather than as "meta http-equiv" tags). This test assumes the following
+ // headers are set in the .headers file:
+ //
+ // Content-Security-Policy-Report-Only: trusted-types ...; report-uri ...
+
+ // Return function that returns a promise that resolves on the given
+ // violation report.
+ function expect_violation(filter) {
+ return new Promise((resolve, reject) => {
+ function handler(e) {
+ if (e.originalPolicy.includes(filter)) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ // A sample policy we use to test trustedTypes.createPolicy behaviour.
+ const id = x => x;
+ const policy = trustedTypes.createPolicy("two", {
+ createHTML: id,
+ createScriptURL: id,
+ createScript: id,
+ });
+/*
+ promise_test(t => {
+ let p = expect_violation("trusted-types two");
+ document.getElementById("script").src = "#abc";
+ assert_true(document.getElementById("script").src.endsWith("#abc"));
+ return p;
+ }, "Trusted Type violation report-only: assign string to script url");
+*/
+
+ promise_test(t => {
+ let p = expect_violation("trusted-types two");
+ document.getElementById("div").innerHTML = "abc";
+ assert_equals(document.getElementById("div").textContent, "abc");
+ return p;
+ }, "Trusted Type violation report-only: assign string to html");
+
+ promise_test(t => {
+ let p = expect_violation("trusted-types two");
+ document.getElementById("script-src").src = "#";
+ assert_true(document.getElementById("script-src").src.endsWith("#"));
+ return p;
+ }, "Trusted Type violation report-only: assign string to script.src");
+
+ promise_test(t => {
+ let p = expect_violation("trusted-types two");
+ document.getElementById("script").innerHTML = "con" + "sole.log('Hello');";
+ assert_true(document.getElementById("script").textContent.startsWith("consol"));
+ return p;
+ }, "Trusted Type violation report-only: assign string to script content");
+
+ promise_test(t => {
+ let p = expect_violation("trusted-types two");
+ document.getElementById("script").src = "#def";
+ return p.then(report => {
+ assert_equals(report.documentURI, "" + window.location);
+ assert_equals(report.disposition, "report");
+ assert_equals(report.effectiveDirective, "require-trusted-types-for");
+ assert_equals(report.violatedDirective, "require-trusted-types-for");
+ assert_true(report.originalPolicy.startsWith("trusted-types two;"));
+ });
+ }, "Trusted Type violation report: check report contents");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html.headers
new file mode 100644
index 0000000000..857a8b31e8
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-report-only.tentative.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy-Report-Only: trusted-types two; report-uri /content-security-policy/resources/dummy-report.php; require-trusted-types-for 'script';
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html b/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html
new file mode 100644
index 0000000000..ae5ac25052
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>Check Trusted Type violation reports</title>
+
+<!-- We assume these HTTP headers are set on the request:
+
+ Set-Cookie: trusted-types-reporting-check-report={{$id:uuid()}}; Path=/trusted-types/
+ Content-Security-Policy-Report-Only: \
+ trusted-types one two; \
+ report-uri /reporting/resources/report.py?op=put&reportID={{$id}}
+-->
+</head>
+<body>
+ <script>
+ trustedTypes.createPolicy("three", {});
+ </script>
+ <script async defer src='../content-security-policy/support/checkReport.sub.js?reportField=violated-directive&reportValue=trusted-types'></script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html.sub.headers b/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html.sub.headers
new file mode 100644
index 0000000000..c055bdc656
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-reporting-check-report.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: trusted-types-reporting-check-report={{$id:uuid()}}; Path=/trusted-types/
+Content-Security-Policy-Report-Only: trusted-types one two; report-uri /reporting/resources/report.py?op=put&reportID={{$id}}
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html
new file mode 100644
index 0000000000..9db307db60
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html
@@ -0,0 +1,279 @@
+<!DOCTYPE html>
+<head>
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/content-security-policy/support/testharness-helper.js"></script>
+</head>
+<body>
+ <script>
+ // CSP insists the "trusted-types: ..." directives are delivered as headers
+ // (rather than as "<meta http-equiv" tags). This test assumes the following
+ // headers are set in the .headers file:
+ //
+ // Content-Security-Policy: trusted-types one
+ // Content-Security-Policy-Report-Only: trusted-types two; report-uri ...
+ // Content-Security-Policy: object-src 'none'
+ // Content-Security-Policy: default-src * 'unsafe-inline'
+ //
+ // The third rule is there so we can provoke a CSP violation report at will.
+ // The intent is that in order to test that a violation has *not* been thrown
+ // (and without resorting to abominations like timeouts), we force a *another*
+ // CSP violation (by violating the object-src rule) and when that event is
+ // processed we can we sure that an earlier event - if it indeed occurred -
+ // must have already been processed.
+ //
+ // The last rule allows all scripting except 'unsafe-eval', so we can also
+ // test reporting of this case.
+
+ const url = "" + document.location;
+
+ // Return function that returns a promise that resolves on the given
+ // violation report.
+ //
+ // filter_arg - iff function, call it with the event object.
+ // Else, string-ify and compare against event.originalPolicy.
+ function promise_violation(filter_arg) {
+ return _ => new Promise((resolve, reject) => {
+ function handler(e) {
+ let matches = (filter_arg instanceof Function)
+ ? filter_arg(e)
+ : (e.originalPolicy.includes(filter_arg));
+ if (matches) {
+ document.removeEventListener("securitypolicyviolation", handler);
+ e.stopPropagation();
+ resolve(e);
+ }
+ }
+ document.addEventListener("securitypolicyviolation", handler);
+ });
+ }
+
+ // Like assert_throws_*, but we don't care about the exact error. We just want
+ // to run the code and continue.
+ function expect_throws(fn) {
+ try { fn(); assert_unreached(); } catch (err) { /* ignore */ }
+ }
+
+ // Test the "sample" field of the event.
+ // TODO(vogelheim): The current set of tests allows for more variance in the
+ // sample reports than the current spec draft does. Once the spec has
+ // been finalized, we should clamp this down to check byte-for-byte
+ // against the values mandated by the spec.
+
+ function expect_sample(s) { return e => {
+ assert_true(e.sample.includes(s),
+ `expected "${e.sample}" to include "${s}".`);
+ return e;
+ } }
+
+ function expect_blocked_uri(s) { return e => {
+ assert_equals(e.blockedURI, s,
+ `expected "${e.blockedURI}" to be "${s}".`);
+ return e;
+ } }
+
+ // A sample policy we use to test trustedTypes.createPolicy behaviour.
+ const id = x => x;
+ const a_policy = {
+ createHTML: id,
+ createScriptURL: id,
+ createScript: id,
+ };
+
+ // Provoke/wait for a CSP violation, in order to be sure that all previous
+ // CSP violations have been delivered.
+ function promise_flush() {
+ return promise_violation("object-src 'none'");
+ }
+ function flush() {
+ expect_throws(_ => {
+ var o = document.createElement('object');
+ o.type = "application/x-shockwave-flash";
+ document.body.appendChild(o);
+ });
+ }
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("trusted-types one"))
+ .then(promise_violation("trusted-types two"))
+ .then(expect_sample("three"))
+ .then(expect_blocked_uri("trusted-types-policy"))
+ .then(promise_flush());
+ expect_throws(_ => trustedTypes.createPolicy("three", a_policy));
+ flush();
+ return p;
+ }, "Trusted Type violation report: creating a forbidden policy.");
+
+ promise_test(t => {
+ let p = promise_flush()();
+ expect_throws(_ => trustedTypes.createPolicy("two", a_policy));
+ flush();
+ return p;
+ }, "Trusted Type violation report: creating a report-only-forbidden policy.");
+
+ // policy_one is set below, and used in several tests further down.
+ let policy_one = null;
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("trusted-types two"))
+ .then(promise_flush());
+ policy_one = trustedTypes.createPolicy("one", a_policy);
+ flush();
+ return p;
+ }, "Trusted Type violation report: creating a forbidden-but-not-reported policy.");
+
+ promise_test(t => {
+ let p = promise_violation("require-trusted-types-for 'script'")();
+ expect_throws(_ => document.getElementById("script").src = url);
+ return p;
+ }, "Trusted Type violation report: assign string to script url");
+
+ promise_test(t => {
+ let p = promise_violation("require-trusted-types-for 'script'")();
+ expect_throws(_ => document.getElementById("div").innerHTML = "abc");
+ return p;
+ }, "Trusted Type violation report: assign string to html");
+
+ promise_test(t => {
+ let p = promise_flush()();
+ document.getElementById("script").text = policy_one.createScript("2+2;");
+ flush();
+ return p;
+ }, "Trusted Type violation report: assign trusted script to script; no report");
+
+ promise_test(t => {
+ let p = promise_flush()();
+ document.getElementById("div").innerHTML = policy_one.createHTML("abc");
+ flush();
+ return p;
+ }, "Trusted Type violation report: assign trusted HTML to html; no report");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("Element innerHTML|abc"));
+ expect_throws(_ => { document.getElementById("div").innerHTML = "abc" });
+ return p;
+ }, "Trusted Type violation report: sample for innerHTML assignment");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("HTMLScriptElement text|abc"));
+ expect_throws(_ => { document.getElementById("script").text = "abc" });
+ return p;
+ }, "Trusted Type violation report: sample for text assignment");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("HTMLScriptElement src"));
+ expect_throws(_ => { document.getElementById("script").src = "" });
+ return p;
+ }, "Trusted Type violation report: sample for script.src assignment");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("HTMLElement innerText|2+2;"));
+ expect_throws(_ => document.getElementById("script").innerText = "2+2;");
+ return p;
+ }, "Trusted Type violation report: sample for script innerText assignment");
+
+ // TODO(lyf): https://crbug.com/1066791 Following tests which related to svg
+ // script element cause a flaky timeout in `linux-blink-rel`, following tests
+ // should be added back after the bug fix.
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("SVGAnimatedString baseVal"));
+ expect_throws(_ => { document.getElementById("svgscript").href.baseVal = "" });
+ return p;
+ }, "Trusted Type violation report: sample for SVGScriptElement href assignment");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("Element setAttribute"));
+ expect_throws(_ => { document.getElementById("svgscript").setAttribute('href', "test"); });
+ return p;
+ }, "Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("SVGScriptElement text"));
+ expect_throws(_ => { document.getElementById("svgscript").insertBefore(document.createTextNode("Hello"), null) });
+ return p;
+ }, "Trusted Type violation report: sample for SVGScriptElement text assignment");
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("eval|2+2"))
+ .then(promise_flush());
+ expect_throws(_ => eval("2+2"));
+ flush();
+ return p;
+ }, "Trusted Type violation report: sample for eval");
+
+ promise_test(t => {
+ // We expect the sample string to always contain the name, and at least the
+ // start of the value, but it should not be excessively long.
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("HTMLElement innerText|abbb"))
+ .then(e => assert_less_than(e.sample.length, 150));
+ const value = "a" + "b".repeat(50000);
+ expect_throws(_ => document.getElementById("script").innerText = value);
+ return p;
+ }, "Trusted Type violation report: large values should be handled sanely.");
+
+ // Test reporting for Custom Elements (where supported). The report should
+ // refer to the DOM elements being modified, so that Custom Elements cannot
+ // "mask" the underlying DOM mechanism (for reporting).
+ if (customElements) {
+ class CustomScript extends HTMLScriptElement {};
+ customElements.define("custom-script", CustomScript, { extends: "script" });
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("HTMLScriptElement src|abc"));
+ expect_throws(_ => document.getElementById("customscript").src = "abc");
+ return p;
+ }, "Trusted Type violation report: sample for custom element assignment");
+ }
+
+ promise_test(t => {
+ let p = Promise.resolve()
+ .then(promise_violation("require-trusted-types-for 'script'"))
+ .then(expect_blocked_uri("trusted-types-sink"))
+ .then(expect_sample("Worker constructor|"))
+ .then(promise_flush());
+ expect_throws(_ => new Worker("blabla"));
+ flush();
+ return p;
+ }, "Trusted Type violation report: Worker constructor");
+
+ </script>
+
+ <!-- Some elements for the tests to act on. -->
+ <div id="div"></div>
+ <script id="script"></script>
+ <script id="customscript" is="custom-script" src="a"></script>
+ <svg><script id="svgscript"></script></svg>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html.headers b/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html.headers
new file mode 100644
index 0000000000..31c8e41317
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-reporting.tentative.html.headers
@@ -0,0 +1,6 @@
+Content-Security-Policy: trusted-types one
+Content-Security-Policy-Report-Only: trusted-types two; report-uri /content-security-policy/resources/dummy-report.php
+Content-Security-Policy: object-src 'none'
+Content-Security-Policy: default-src * 'unsafe-inline'
+Content-Security-Policy: require-trusted-types-for 'script'
+
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-source-file-path.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-source-file-path.tentative.html
new file mode 100644
index 0000000000..6e87c25a7f
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-source-file-path.tentative.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<head>
+ <title>
+ Check the reported TrustedType violation's sourceFile.
+ </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/get-host-info.sub.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="require-trusted-types-for 'script'; trusted-types id">
+ </head>
+<body>
+
+<script id="to-be-modified"></script>
+<script>
+let toBeModified = document.querySelector("#to-be-modified");
+
+let id_policy = trustedTypes.createPolicy("id", {
+ createHTML: x => x,
+ createScriptURL: x => x,
+ createScript: x => x,
+});
+
+function futureViolation() {
+ return new Promise(r => addEventListener("securitypolicyviolation", r), {
+ once: true
+ });
+}
+
+function futureScript(url) {
+ return new Promise(r => {
+ let script = document.createElement("script");
+ script.src = id_policy.createScriptURL(url);
+ script.onload = r;
+ document.body.appendChild(script);
+ });
+}
+
+promise_test(async t => {
+ let future_violation = futureViolation();
+ assert_throws_js(TypeError, _ => {
+ document.getElementById("to-be-modified").innerHTML = "'test'";
+ });
+ let violation = await future_violation;
+ assert_equals(violation.sourceFile, location.href)
+}, "same-document script")
+
+promise_test(async t => {
+ let script_origin = get_host_info().HTTP_ORIGIN;
+ let script_src = script_origin +
+ "/trusted-types/support/set-inner-html.js";
+ let script = await futureScript(script_src);
+ let future_violation = futureViolation();
+ assert_throws_js(TypeError, () => setInnerHtml(toBeModified, "'test'"));
+ let violation = await future_violation;
+ assert_equals(violation.sourceFile, script_src);
+}, "same-origin script")
+
+promise_test(async t => {
+ let script_origin = get_host_info().HTTP_REMOTE_ORIGIN;
+ let script_src = script_origin +
+ "/trusted-types/support/set-inner-html.js";
+ let script = await futureScript(script_src);
+ let future_violation = futureViolation();
+ assert_throws_js(TypeError, () => setInnerHtml(toBeModified, "'test'"));
+ let violation = await future_violation;
+ assert_equals(violation.sourceFile, script_src);
+}, "cross-origin script")
+
+// TODO(arthursonzogni): Check what happens with redirects. Do we report the
+// request's URL or the response's URL?
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-svg-script.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-svg-script.tentative.html
new file mode 100644
index 0000000000..946f825fa3
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-svg-script.tentative.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy"
+ content="require-trusted-types-for 'script'">
+</head>
+<body>
+ <div id="log"></div>
+ <svg id="svg"><script id="script">"some script text";</script></svg>
+ <script>
+ // Returns a promise that resolves with a Security Policy Violation (spv)
+ // even when it is received.
+ function promise_spv() {
+ return new Promise((resolve, reject) => {
+ window.addEventListener("securitypolicyviolation", e => {
+ resolve(e);
+ }, { once: true });
+ });
+ }
+
+ const policy = trustedTypes.createPolicy("policy", {
+ createScript: x => x, createHTML: x => x, createScriptURL: x => x });
+
+ promise_test(t => {
+ assert_throws_js(TypeError, _ => {
+ document.getElementById("script").innerHTML = "'modified via innerHTML';";
+ });
+ return promise_spv();
+ }, "Assign String to SVGScriptElement.innerHTML.");
+
+ promise_test(t => {
+ document.getElementById("script").innerHTML = policy.createHTML("'modified via innerHTML';");
+ return Promise.resolve();
+ }, "Assign TrustedHTML to SVGScriptElement.innerHTML.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.innerHTML = policy.createHTML("'modified via innerHTML';");
+ document.getElementById("svg").appendChild(elem);
+ return promise_spv();
+ }, "Assign TrustedHTML to SVGScriptElement.innerHTML and execute it.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.insertBefore(document.createTextNode("modified via DOM"), null);
+ document.getElementById("svg").appendChild(elem);
+ return promise_spv();
+ }, "Modify SVGScriptElement via DOM manipulation.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ assert_throws_js(TypeError, _ => {
+ elem.href.baseVal = "about:blank";
+ });
+ document.getElementById("svg").appendChild(elem);
+ return promise_spv();
+ }, "Assign string to SVGScriptElement.href.baseVal.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.href.baseVal = policy.createScriptURL("about:blank");
+ document.getElementById("svg").appendChild(elem);
+ return Promise.resolve();
+ }, "Assign TrustedScriptURL to SVGScriptElement.href.baseVal.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ assert_throws_js(TypeError, _ => {
+ elem.setAttribute("href", "about:blank");
+ });
+ document.getElementById("svg").appendChild(elem);
+ return promise_spv();
+ }, "Assign string to non-attached SVGScriptElement.href via setAttribute.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.setAttribute("href", policy.createScriptURL("about:blank"));
+ document.getElementById("svg").appendChild(elem);
+ return Promise.resolve();
+ }, "Assign TrustedScriptURL to non-attached SVGScriptElement.href via setAttribute.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ document.getElementById("svg").appendChild(elem);
+ assert_throws_js(TypeError, _ => {
+ elem.setAttribute("href", "about:blank");
+ });
+ return promise_spv();
+ }, "Assign string to attached SVGScriptElement.href via setAttribute.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ document.getElementById("svg").appendChild(elem);
+ elem.setAttribute("href", policy.createScriptURL("about:blank"));
+ return Promise.resolve();
+ }, "Assign TrustedScriptURL to attached SVGScriptElement.href via setAttribute.");
+
+ // Default policy test: We repate the string assignment tests above,
+ // but now expect all of them to pass.
+ promise_test(t => {
+ trustedTypes.createPolicy("default", {
+ createScript: x => x, createHTML: x => x, createScriptURL: x => x });
+ return Promise.resolve();
+ }, "Setup default policy");
+
+ promise_test(t => {
+ document.getElementById("script").innerHTML = "'modified via innerHTML';";
+ return Promise.resolve();
+ }, "Assign String to SVGScriptElement.innerHTML w/ default policy.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.href.baseVal = "about:blank";
+ document.getElementById("svg").appendChild(elem);
+ return Promise.resolve();
+ }, "Assign string to SVGScriptElement.href.baseVal w/ default policy.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ elem.setAttribute("href", "about:blank");
+ document.getElementById("svg").appendChild(elem);
+ return Promise.resolve();
+ }, "Assign string to non-attached SVGScriptElement.href via setAttribute w/ default policy.");
+
+ promise_test(t => {
+ const elem = document.createElementNS(
+ "http://www.w3.org/2000/svg", "script");
+ document.getElementById("svg").appendChild(elem);
+ elem.setAttribute("href", "about:blank");
+ return Promise.resolve();
+ }, "Assign string to attached SVGScriptElement.href via setAttribute w/ default policy.");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/trusted-types-tojson.tentative.html b/testing/web-platform/tests/trusted-types/trusted-types-tojson.tentative.html
new file mode 100644
index 0000000000..72c5383099
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/trusted-types-tojson.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="trusted-types foo">
+</head>
+<body>
+<script>
+test(t => {
+ let policy = trustedTypes.createPolicy("foo", {
+ createHTML: h => h,
+ createScript: s => s,
+ createScriptURL: u => u,
+ });
+
+ assert_equals(JSON.stringify({"x": policy.createHTML("<p>foo</p>")}),
+ "{\"x\":\"<p>foo</p>\"}");
+ assert_equals(JSON.stringify({"x": policy.createScript("foo(bar)")}),
+ "{\"x\":\"foo(bar)\"}");
+ assert_equals(JSON.stringify({"x": policy.createScriptURL("https://foo.example.com/bar")}),
+ "{\"x\":\"https://foo.example.com/bar\"}");
+}, "toJSON");
+</script>
+</body>
diff --git a/testing/web-platform/tests/trusted-types/tt-block-eval.tentative.html b/testing/web-platform/tests/trusted-types/tt-block-eval.tentative.html
new file mode 100644
index 0000000000..13178bd44b
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/tt-block-eval.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
+</head>
+<body>
+<script>
+ trustedTypes.createPolicy("default", {createScript: _ => null});
+
+ test(t => {
+ let a = 0;
+ assert_throws_js(EvalError, _ => {
+ eval('a="hello there"');
+ });
+ assert_equals(a, 0);
+ }, "eval blocks if the default policy rejects a value.");
+</script>
diff --git a/testing/web-platform/tests/trusted-types/worker-constructor.https.html b/testing/web-platform/tests/trusted-types/worker-constructor.https.html
new file mode 100644
index 0000000000..6e127b11a5
--- /dev/null
+++ b/testing/web-platform/tests/trusted-types/worker-constructor.https.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<html>
+<head>
+ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+const test_url = "support/WorkerGlobalScope-importScripts.https.js"
+const trusted_url = trustedTypes.createPolicy("anythinggoes", {
+ createScriptURL: x => x}).createScriptURL(test_url);
+const default_url = "support/WorkerGlobalScope-importScripts.potato.js"
+
+async function service_worker(url) {
+ if (!('serviceWorker' in navigator)) return Promise.resolve();
+
+ const scope = 'support/some/scope/for/this/test';
+ const reg = await navigator.serviceWorker.getRegistration(scope);
+ if (reg) await reg.unregister();
+ return await navigator.serviceWorker.register(url, {scope});
+}
+
+// Most tests below don't need promises, but the ones related to
+// ServiceWorkers do. Since we can't mix promise and non-promise tests,
+// we'll just run the non-promise tests in the main function and return
+// an empty-resolved promise for those.
+// Since an active default policy will affect all subsequent DOM operations,
+// we're wrapping policy creation in a promise_test. Together, this will
+// force proper serialization of all tests.
+//
+// Generally, we don't actually care what the workers here do, we'll merely
+// check whether creation succeeds.
+
+promise_test(t => {
+ new Worker(trusted_url);
+ return Promise.resolve();
+}, "Create Worker via ScriptTestUrl");
+
+promise_test(t => {
+ new SharedWorker(trusted_url);
+ return Promise.resolve();
+}, "Create SharedWorker via ScriptTestUrl");
+
+promise_test(t => {
+ return service_worker(trusted_url);
+}, "Create ServiceWorker via ScriptTestUrl");
+
+promise_test(t => {
+ assert_throws_js(TypeError, () => new Worker(test_url));
+ return Promise.resolve();
+}, "Block Worker creation via string");
+
+promise_test(t => {
+ assert_throws_js(TypeError, () => new SharedWorker(test_url));
+ return Promise.resolve();
+}, "Block SharedWorker creation via string");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, service_worker(test_url));
+}, "Block ServiceWorker creation via String");
+
+// Tests with default policy.
+promise_test(t => {
+ trustedTypes.createPolicy("default", {
+ createScriptURL: s => s.replace("potato", "https") });
+ return Promise.resolve();
+}, "Setup default policy.");
+
+promise_test(t => {
+ new Worker(default_url);
+ return Promise.resolve();
+}, "Create Worker via string with default policy.");
+
+promise_test(t => {
+ new SharedWorker(default_url);
+ return Promise.resolve();
+}, "Create SharedWorker via string with default policy.");
+
+promise_test(t => {
+ return service_worker(default_url);
+}, "Create ServiceWorker via string with default policy.");
+
+</script>
+</body>