[appmanifest] add CORS/CSP tests for icons and shortcuts (#27620)

diff --git a/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html b/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html
new file mode 100644
index 0000000..a6acdd4
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Test that icons member is supported (CORS violation)</title>
+<link rel="help" href="https://w3c.github.io/manifest#icons-member" />
+<link rel="manifest" href="icons-member-cors-fail.sub.webmanifest" />
+<h1>Testing support for icons member (CORS violation)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the icon <strong>must not</strong> show a white cross on a red background.
+</p>
diff --git a/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest b/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest
new file mode 100644
index 0000000..e8b9327
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest
@@ -0,0 +1,7 @@
+{
+    "icons": [{
+        "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/fail.png",
+        "sizes": "256x256",
+        "type": "image/png"
+    }]
+}
diff --git a/appmanifest/icons-member/icons-member-cors-fail.webmanifest.headers b/appmanifest/icons-member/icons-member-cors-fail.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors-fail.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/icons-member/icons-member-cors-manual.sub.html b/appmanifest/icons-member/icons-member-cors-manual.sub.html
new file mode 100644
index 0000000..a54f362
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors-manual.sub.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Test that icons member is supported (via CORS)</title>
+<link rel="help" href="https://w3c.github.io/manifest#icons-member" />
+<link rel="manifest" href="icons-member-cors.sub.webmanifest" />
+<h1>Testing support for icons member (via CORS)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the icon must show a white check mark on a green background.
+</p>
diff --git a/appmanifest/icons-member/icons-member-cors.sub.webmanifest b/appmanifest/icons-member/icons-member-cors.sub.webmanifest
new file mode 100644
index 0000000..5d95262
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors.sub.webmanifest
@@ -0,0 +1,7 @@
+{
+    "icons": [{
+        "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png",
+        "sizes": "256x256",
+        "type": "image/png"
+    }]
+}
diff --git a/appmanifest/icons-member/icons-member-cors.webmanifest.headers b/appmanifest/icons-member/icons-member-cors.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-cors.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html b/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html
new file mode 100644
index 0000000..7f35fc3
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}">
+<title>Test that icons member is supported (CSP violation)</title>
+<link rel="help" href="https://w3c.github.io/manifest#icons-member" />
+<link rel="manifest" href="icons-member-csp-fail.webmanifest" />
+<h1>Testing support for icons member (CSP violation)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the icon <strong>must not</strong> show a white cross on a red background.
+</p>
diff --git a/appmanifest/icons-member/icons-member-csp-fail.webmanifest b/appmanifest/icons-member/icons-member-csp-fail.webmanifest
new file mode 100644
index 0000000..a173648
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp-fail.webmanifest
@@ -0,0 +1,7 @@
+{
+    "icons": [{
+        "src": "fail.png",
+        "sizes": "256x256",
+        "type": "image/png"
+    }]
+}
diff --git a/appmanifest/icons-member/icons-member-csp-fail.webmanifest.headers b/appmanifest/icons-member/icons-member-csp-fail.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp-fail.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/icons-member/icons-member-csp-manual.sub.html b/appmanifest/icons-member/icons-member-csp-manual.sub.html
new file mode 100644
index 0000000..15e0912
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp-manual.sub.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}">
+<title>Test that icons member is supported (CSP check)</title>
+<link rel="help" href="https://w3c.github.io/manifest#icons-member" />
+<link rel="manifest" href="icons-member-csp.sub.webmanifest" />
+<h1>Testing support for icons member (CSP check)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the icon must show a white check mark on a green background.
+</p>
diff --git a/appmanifest/icons-member/icons-member-csp.sub.webmanifest b/appmanifest/icons-member/icons-member-csp.sub.webmanifest
new file mode 100644
index 0000000..5d95262
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp.sub.webmanifest
@@ -0,0 +1,7 @@
+{
+    "icons": [{
+        "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png",
+        "sizes": "256x256",
+        "type": "image/png"
+    }]
+}
diff --git a/appmanifest/icons-member/icons-member-csp.webmanifest.headers b/appmanifest/icons-member/icons-member-csp.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/icons-member/icons-member-csp.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/icons-member/pass.png.sub.headers b/appmanifest/icons-member/pass.png.sub.headers
new file mode 100644
index 0000000..adf190a
--- /dev/null
+++ b/appmanifest/icons-member/pass.png.sub.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: https://{{host}}:{{ports[https][0]}}
diff --git a/appmanifest/shortcuts-member/pass.png.sub.headers b/appmanifest/shortcuts-member/pass.png.sub.headers
new file mode 100644
index 0000000..adf190a
--- /dev/null
+++ b/appmanifest/shortcuts-member/pass.png.sub.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: https://{{host}}:{{ports[https][0]}}
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors-fail-manual.sub.html b/appmanifest/shortcuts-member/shortcuts-member-cors-fail-manual.sub.html
new file mode 100644
index 0000000..06ea5af
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors-fail-manual.sub.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Test that shortcuts member is supported (icon violates CORS)</title>
+<link rel="help" href="https://w3c.github.io/manifest/#shortcuts-member" />
+<link rel="manifest" href="shortcuts-member-cors-fail.sub.webmanifest" />
+<h1>Testing support for shortcuts member (icon violates CORS)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the application <strong>must not</strong> show a shortcut with
+    a white cross on red background.
+</p>
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors-fail.sub.webmanifest b/appmanifest/shortcuts-member/shortcuts-member-cors-fail.sub.webmanifest
new file mode 100644
index 0000000..3edb9aa
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors-fail.sub.webmanifest
@@ -0,0 +1,14 @@
+{
+    "name": "Shortcut test",
+    "scope": "/",
+    "shortcuts": [{
+        "name": "pass",
+        "short_name": "",
+        "description": "",
+        "url": "shortcut_pass.html",
+        "icons": [{
+            "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/fail.png",
+            "sizes": "256x256"
+        }]
+    }]
+}
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors-fail.webmanifest.headers b/appmanifest/shortcuts-member/shortcuts-member-cors-fail.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors-fail.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors-manual.sub.html b/appmanifest/shortcuts-member/shortcuts-member-cors-manual.sub.html
new file mode 100644
index 0000000..a4fc016
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors-manual.sub.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Test that shortcuts member is supported (icon via CORS)</title>
+<link rel="help" href="https://w3c.github.io/manifest/#shortcuts-member" />
+<link rel="manifest" href="shortcuts-member-cors.sub.webmanifest" />
+<h1>Testing support for shortcuts member (icon via CORS)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the application must show a shortcut named "pass" with a check
+    mark icon. Clicking it must open this document again.
+</p>
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors.sub.webmanifest b/appmanifest/shortcuts-member/shortcuts-member-cors.sub.webmanifest
new file mode 100644
index 0000000..9e17c18
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors.sub.webmanifest
@@ -0,0 +1,14 @@
+{
+    "name": "Shortcut test",
+    "scope": "/",
+    "shortcuts": [{
+        "name": "pass",
+        "short_name": "",
+        "description": "",
+        "url": "shortcut_pass.html",
+        "icons": [{
+            "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png",
+            "sizes": "256x256"
+        }]
+    }]
+}
diff --git a/appmanifest/shortcuts-member/shortcuts-member-cors.webmanifest.headers b/appmanifest/shortcuts-member/shortcuts-member-cors.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-cors.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp-fail-manual.sub.html b/appmanifest/shortcuts-member/shortcuts-member-csp-fail-manual.sub.html
new file mode 100644
index 0000000..60a2601
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp-fail-manual.sub.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}">
+<title>Test that shortcuts member is supported (icon CSP violation)</title>
+<link rel="help" href="https://w3c.github.io/manifest/#shortcuts-member" />
+<link rel="manifest" href="shortcuts-member-cors-fail.sub.webmanifest" />
+<h1>Testing support for shortcuts member (icon CSP violation)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the application <strong>must not</strong> show a shortcut with
+    a white cross on red background.
+</p>
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest b/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest
new file mode 100644
index 0000000..47f15dd
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest
@@ -0,0 +1,14 @@
+{
+    "name": "Shortcut test",
+    "scope": "/",
+    "shortcuts": [{
+        "name": "pass",
+        "short_name": "",
+        "description": "",
+        "url": "shortcut_pass.html",
+        "icons": [{
+            "src": "fail.png",
+            "sizes": "256x256"
+        }]
+    }]
+}
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest.headers b/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp-fail.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp-manual.sub.html b/appmanifest/shortcuts-member/shortcuts-member-csp-manual.sub.html
new file mode 100644
index 0000000..09cb58f
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp-manual.sub.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}">
+<title>Test that shortcuts member is supported (icon CSP check)</title>
+<link rel="help" href="https://w3c.github.io/manifest/#shortcuts-member" />
+<link rel="manifest" href="shortcuts-member-cors.sub.webmanifest" />
+<h1>Testing support for shortcuts member (icon CSP check)</h1>
+<script>
+    // Force the port of the origin to be ports[https][0] (likely :8443)
+    // we treat the port ports[https][1] (likely :8444) to be another origin that we fail against
+    if (window.location.origin !== "https://{{host}}:{{ports[https][0]}}") {
+        window.location = new URL(window.location.pathname, "https://{{host}}:{{ports[https][0]}}")
+    }
+</script>
+<p>
+    To pass, the application must show a shortcut named "pass" with a check
+    mark icon. Clicking it must open this document again.
+</p>
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp.sub.webmanifest b/appmanifest/shortcuts-member/shortcuts-member-csp.sub.webmanifest
new file mode 100644
index 0000000..9e17c18
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp.sub.webmanifest
@@ -0,0 +1,14 @@
+{
+    "name": "Shortcut test",
+    "scope": "/",
+    "shortcuts": [{
+        "name": "pass",
+        "short_name": "",
+        "description": "",
+        "url": "shortcut_pass.html",
+        "icons": [{
+            "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png",
+            "sizes": "256x256"
+        }]
+    }]
+}
diff --git a/appmanifest/shortcuts-member/shortcuts-member-csp.webmanifest.headers b/appmanifest/shortcuts-member/shortcuts-member-csp.webmanifest.headers
new file mode 100644
index 0000000..2bab061
--- /dev/null
+++ b/appmanifest/shortcuts-member/shortcuts-member-csp.webmanifest.headers
@@ -0,0 +1 @@
+Content-Type: application/manifest+json; charset=utf-8