From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- .../html/cross-origin-embedder-policy/META.yml | 9 + .../html/cross-origin-embedder-policy/README.md | 1 + .../about-blank-popup.https.html | 59 +++++ .../about-blank-popup.https.html.headers | 1 + .../cross-origin-embedder-policy/blob.https.html | 44 ++++ .../blob.https.html.headers | 1 + ...lock-local-documents-inheriting-none.https.html | 112 +++++++++ ...e-storage-reporting-dedicated-worker.https.html | 51 +++++ .../cache-storage-reporting-document.https.html | 58 +++++ ...che-storage-reporting-service-worker.https.html | 64 ++++++ ...ache-storage-reporting-shared-worker.https.html | 49 ++++ .../coep-frame-javascript.https.html | 25 ++ ...coep-on-response-from-service-worker.https.html | 111 +++++++++ .../credentialless/META.yml | 7 + .../credentialless/README.md | 3 + .../credentialless/cache-storage.https.window.js | 150 ++++++++++++ .../credentialless/cache.window.js | 84 +++++++ .../credentialless/cross-origin-isolated.window.js | 49 ++++ .../dedicated-worker.https.window.js | 123 ++++++++++ .../credentialless/fetch.https.window.js | 127 +++++++++++ .../iframe-coep-credentialless.https.window.js | 37 +++ .../iframe-coep-none.https.window.js | 22 ++ .../iframe-coep-require-corp.https.window.js | 38 ++++ .../credentialless/iframe.window.js | 47 ++++ .../credentialless/image.https.window.js | 97 ++++++++ .../credentialless/link.https.window.js | 99 ++++++++ .../credentialless/redirect.window.js | 55 +++++ .../reporting-navigation.https.window.js | 139 ++++++++++++ .../reporting-subresource-corp.https.window.js | 74 ++++++ .../credentialless/resources/common.js | 134 +++++++++++ .../credentialless/resources/iframeTest.js | 85 +++++++ .../credentialless/script.https.window.js | 99 ++++++++ ...orker-coep-credentialless-proxy.https.window.js | 85 +++++++ .../service-worker-coep-none-proxy.https.window.js | 87 +++++++ .../credentialless/service-worker.https.window.js | 113 ++++++++++ .../credentialless/shared-worker.https.window.js | 119 ++++++++++ .../credentialless/video.https.window.js | 53 +++++ .../credentialless/video.https.window.js.headers | 1 + ...igin-isolated-permission-iframe.https.window.js | 74 ++++++ ...lated-permission-iframe.https.window.js.headers | 2 + ...igin-isolated-permission-worker.https.window.js | 170 ++++++++++++++ ...lated-permission-worker.https.window.js.headers | 2 + .../cross-origin-embedder-policy/data.https.html | 20 ++ .../data.https.html.headers | 1 + .../dedicated-worker-cache-storage.https.html | 128 +++++++++++ .../dedicated-worker.https.html | 214 ++++++++++++++++++ .../header-parsing.https.html | 85 +++++++ .../iframe-history-none-require-corp.https.html | 54 +++++ .../javascript.https.html | 21 ++ .../javascript.https.html.headers | 1 + .../meta-http-equiv.https.html | 20 ++ .../multi-globals/current/current.html | 3 + .../multi-globals/current/current.html.headers | 1 + .../multi-globals/current/worker.js | 1 + .../multi-globals/incumbent/incumbent.html | 14 ++ .../multi-globals/incumbent/incumbent.html.headers | 1 + .../multi-globals/incumbent/worker.js | 1 + .../multi-globals/worker.js | 1 + .../multi-globals/workers-coep-report.https.html | 49 ++++ .../workers-coep-report.https.html.headers | 1 + .../no-secure-context.html | 19 ++ .../no-secure-context.html.headers | 1 + .../non-initial-about-blank.https.html | 21 ++ .../non-initial-about-blank.https.html.headers | 1 + .../none-load-from-cache-storage.https.html | 173 ++++++++++++++ .../none-sw-from-none.https.html | 89 ++++++++ .../none-sw-from-require-corp.https.html | 93 ++++++++ .../none-sw-from-require-corp.https.html.headers | 1 + .../cross-origin-embedder-policy/none.https.html | 91 ++++++++ .../none.https.html.headers | 1 + ...eflection-credentialless.tentative.https.any.js | 2 + ...n-credentialless.tentative.https.any.js.headers | 1 + .../reflection-require-corp.tentative.https.any.js | 2 + ...ion-require-corp.tentative.https.any.js.headers | 1 + .../reflection-unsafe-none.tentative.https.any.js | 2 + .../report-only-require-corp.https.html | 86 +++++++ .../report-only-require-corp.https.html.headers | 1 + .../reporting-navigation.https.html | 170 ++++++++++++++ .../reporting-subresource-corp.https.html | 206 +++++++++++++++++ ...-to-document-reporting-endpoint.https.window.js | 140 ++++++++++++ .../reporting-to-endpoint.https.html | 209 +++++++++++++++++ .../reporting-to-endpoint.https.html.sub.headers | 1 + .../reporting-to-frame-owner.https.html | 87 +++++++ .../reporting-to-worker-owner.https.html | 89 ++++++++ .../require-corp-about-blank.https.html | 48 ++++ .../require-corp-about-blank.https.html.headers | 1 + .../require-corp-about-srcdoc.https.html | 48 ++++ .../require-corp-about-srcdoc.https.html.headers | 1 + .../require-corp-cached-images.https.html | 74 ++++++ .../require-corp-cached-images.https.html.headers | 1 + ...require-corp-load-from-cache-storage.https.html | 179 +++++++++++++++ ...corp-load-from-cache-storage.https.html.headers | 1 + .../require-corp-revalidated-images.https.html | 76 +++++++ .../require-corp-sw-from-none.https.html | 92 ++++++++ .../require-corp-sw-from-require-corp.https.html | 93 ++++++++ ...re-corp-sw-from-require-corp.https.html.headers | 1 + .../require-corp-sw.https.html | 53 +++++ .../require-corp-worker-script-revalidation.html | 25 ++ .../require-corp.https.html | 251 +++++++++++++++++++++ .../require-corp.https.html.headers | 1 + .../resources/blob-url-factory.html | 24 ++ .../resources/blob-url-factory.html.headers | 2 + .../resources/cache-storage-reporting.js | 63 ++++++ .../resources/coep-frame.html | 2 + .../resources/coep-frame.html.headers | 1 + .../resources/common.js | 19 ++ .../resources/corp-image.py | 31 +++ .../dedicated-worker-supporting-revalidation.py | 15 ++ .../resources/dedicated-worker.js | 7 + .../resources/empty-coep.py | 7 + .../resources/fetch-and-create-url.html | 91 ++++++++ .../resources/fetch-in-dedicated-worker.js | 6 + .../resources/iframe.html | 3 + .../resources/load-corp-images.html | 38 ++++ .../resources/load-corp-images.html.headers | 1 + .../resources/navigate-none.sub.html | 34 +++ .../navigate-require-corp-same-site.sub.html | 29 +++ ...avigate-require-corp-same-site.sub.html.headers | 2 + .../resources/navigate-require-corp.sub.html | 24 ++ .../navigate-require-corp.sub.html.headers | 1 + .../resources/nothing-cross-origin-corp.txt | 1 + .../nothing-cross-origin-corp.txt.headers | 1 + .../resources/nothing-same-origin-corp.txt | 1 + .../resources/nothing-same-origin-corp.txt.headers | 1 + .../resources/postmessage-ready.html | 4 + .../resources/report.py | 41 ++++ ...eporting-empty-frame-multiple-headers.html.asis | 9 + .../resources/reporting-empty-frame.html | 5 + .../resources/reporting-worker.js | 25 ++ .../resources/require-corp-sw-import-scripts.js | 23 ++ .../require-corp-sw-import-scripts.js.headers | 1 + .../resources/require-corp-sw.js | 27 +++ .../resources/require-corp-sw.js.headers | 1 + .../resources/script-factory.js | 30 +++ .../resources/shared-worker-fetch.js.py | 24 ++ .../resources/shared-worker.js | 7 + .../resources/sw-store-to-cache-storage.js | 31 +++ .../cross-origin-embedder-policy/resources/sw.js | 12 + .../resources/universal-worker.js | 1 + .../resources/worker-owner-frame.html | 2 + .../resources/worker-owner.js | 36 +++ .../resources/worker-support.js | 81 +++++++ .../sandbox.https.html | 40 ++++ .../sandbox.https.html.headers | 1 + .../service-worker-cache-storage.https.html | 117 ++++++++++ .../shared-workers.https.html | 228 +++++++++++++++++++ .../cross-origin-embedder-policy/srcdoc.https.html | 21 ++ .../srcdoc.https.html.headers | 1 + .../worker-inheritance.sub.https.html | 61 +++++ .../worker-inheritance.sub.https.html.headers | 1 + 150 files changed, 7042 insertions(+) create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/META.yml create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/README.md create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-dedicated-worker.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-document.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-shared-worker.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/coep-frame-javascript.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/coep-on-response-from-service-worker.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/META.yml create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/README.md create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache-storage.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cross-origin-isolated.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-credentialless.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-none.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-require-corp.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/image.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/link.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/redirect.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-navigation.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/common.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/iframeTest.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/script.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-credentialless-proxy.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-none-proxy.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/shared-worker.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/header-parsing.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/iframe-history-none-require-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/meta-http-equiv.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none-load-from-cache-storage.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-none.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-navigation.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-document-reporting-endpoint.https.window.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html.sub.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-frame-owner.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-worker-owner.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-revalidated-images.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-none.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-worker-script-revalidation.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/cache-storage-reporting.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/common.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/corp-image.py create mode 100755 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker-supporting-revalidation.py create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/empty-coep.py create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-in-dedicated-worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/iframe.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/postmessage-ready.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/report.py create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame-multiple-headers.html.asis create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/script-factory.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/shared-worker-fetch.js.py create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/shared-worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/sw-store-to-cache-storage.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/sw.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/universal-worker.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-owner-frame.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-owner.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-support.js create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/shared-workers.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html create mode 100644 testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html.headers (limited to 'testing/web-platform/tests/html/cross-origin-embedder-policy') diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/META.yml b/testing/web-platform/tests/html/cross-origin-embedder-policy/META.yml new file mode 100644 index 0000000000..dc7010880b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/META.yml @@ -0,0 +1,9 @@ +spec: https://html.spec.whatwg.org/multipage/origin.html#coep +suggested_reviewers: + - mikewest + - jugglinmike + - arturjanc + - lweichselbaum + - hemeryar + - ParisMeuleman + - valenting diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/README.md b/testing/web-platform/tests/html/cross-origin-embedder-policy/README.md new file mode 100644 index 0000000000..16179eb013 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/README.md @@ -0,0 +1 @@ +See `../cross-origin-opener-policy/README.md`. diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html new file mode 100644 index 0000000000..2dc73c7561 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html @@ -0,0 +1,59 @@ + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/about-blank-popup.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html new file mode 100644 index 0000000000..ce72f247ef --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html @@ -0,0 +1,44 @@ + + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/blob.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html new file mode 100644 index 0000000000..cf5176606e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html @@ -0,0 +1,112 @@ + + + + + + +
+ + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-dedicated-worker.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-dedicated-worker.https.html new file mode 100644 index 0000000000..f4b2599141 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-dedicated-worker.https.html @@ -0,0 +1,51 @@ + + + + + Check COEP report are send for CacheStorage requests in DedicatedWorker + + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-document.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-document.https.html new file mode 100644 index 0000000000..b998ba7926 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-document.https.html @@ -0,0 +1,58 @@ + + + + + Check COEP report are send for CacheStorage requests in Document. + + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https.html new file mode 100644 index 0000000000..96a328b2cc --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https.html @@ -0,0 +1,64 @@ + + + + + Check COEP report are send for CacheStorage requests in ServiceWorker. + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-shared-worker.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-shared-worker.https.html new file mode 100644 index 0000000000..34af988fc6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cache-storage-reporting-shared-worker.https.html @@ -0,0 +1,49 @@ + + + + + Check COEP report are send for CacheStorage requests in SharedWorker + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-frame-javascript.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-frame-javascript.https.html new file mode 100644 index 0000000000..089019dc2e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-frame-javascript.https.html @@ -0,0 +1,25 @@ + + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-on-response-from-service-worker.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-on-response-from-service-worker.https.html new file mode 100644 index 0000000000..939c618227 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/coep-on-response-from-service-worker.https.html @@ -0,0 +1,111 @@ + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/META.yml b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/META.yml new file mode 100644 index 0000000000..2bf6754a6b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/META.yml @@ -0,0 +1,7 @@ +spec: To be defined. +suggested_reviewers: + - annevk + - arthursonzogni + - arturjanc + - camillelamy + - mikewest diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/README.md b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/README.md new file mode 100644 index 0000000000..86654525dd --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/README.md @@ -0,0 +1,3 @@ +# Related documents: +- https://github.com/mikewest/credentiallessness/ +- https://github.com/w3ctag/design-reviews/issues/582 diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache-storage.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache-storage.https.window.js new file mode 100644 index 0000000000..573e6ac9cb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache-storage.https.window.js @@ -0,0 +1,150 @@ +// META: timeout=long +// META: variant=?document +// META: variant=?dedicated_worker +// META: variant=?shared_worker +// META: variant=?service_worker +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +// Fetch a resource and store it into CacheStorage from |storer| context. Then +// check if it can be retrieved via CacheStorage.match from |retriever| context. +const cacheStorageTest = ( + description, + storer, + retriever, + resource_headers, + request_credential_mode, + expectation +) => { + promise_test_parallel(async test => { + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const url = cross_origin + "/common/square.png?pipe=" + resource_headers + + `&${token()}`; + const this_token = token(); + + // Fetch a request from |stored|. Store the opaque response into + // CacheStorage. + send(storer, ` + const cache = await caches.open("v1"); + const fetch_request = new Request("${url}", { + mode: 'no-cors', + credentials: '${request_credential_mode}' + }); + const fetch_response = await fetch(fetch_request); + await cache.put(fetch_request, fetch_response); + send("${this_token}", "stored"); + `); + assert_equals(await receive(this_token), "stored"); + + // Retrieved it from |retriever|. + send(retriever, ` + const cache = await caches.open("v1"); + try { + const response = await cache.match("${url}"); + send("${this_token}", "retrieved"); + } catch (error) { + send("${this_token}", "error"); + } + `); + assert_equals(await receive(this_token), expectation); + }, description); +}; + +// Execute the same set of tests for every type of execution contexts: +// Documents, DedicatedWorkers, SharedWorkers, and ServiceWorkers. The results +// should be independent of the context. +const environment = location.search.substr(1); +const constructor = environments[environment]; + +const context_none = constructor(coep_none)[0]; +const context_credentialless = constructor(coep_credentialless)[0]; +const context_require_corp = constructor(coep_require_corp)[0]; + +cacheStorageTest(`[${environment}] unsafe-none => unsafe-none`, + context_none, + context_none, + "", + "include", + "retrieved"); +cacheStorageTest(`[${environment}] unsafe-none => credentialless`, + context_none, + context_credentialless, + "", + "include", + "error"); +cacheStorageTest(`[${environment}] unsafe-none => credentialless (omit)`, + context_none, + context_credentialless, + "", + "omit", + "retrieved"); +cacheStorageTest(`[${environment}] unsafe-none => credentialless + CORP`, + context_none, + context_credentialless, + corp_cross_origin, + "include", + "retrieved"); +cacheStorageTest(`[${environment}] unsafe-none => require-corp`, + context_none, + context_require_corp, + "", + "include", + "error"); +cacheStorageTest(`[${environment}] unsafe-none => require-corp (omit)`, + context_none, + context_require_corp, + "", + "include", + "error"); +cacheStorageTest(`[${environment}] unsafe-none => require-corp + CORP`, + context_none, + context_require_corp, + corp_cross_origin, + "include", + "retrieved"); + +cacheStorageTest(`[${environment}] credentialless => unsafe-none`, + context_credentialless, + context_none, + "", + "include", + "retrieved"); +cacheStorageTest(`[${environment}] credentialless => credentialless`, + context_credentialless, + context_credentialless, + "", + "include", + "retrieved"); +cacheStorageTest(`[${environment}] credentialless => require-corp`, + context_credentialless, + context_require_corp, + "", + "include", + "error"); +cacheStorageTest(`[${environment}] credentialless => require-corp + CORP`, + context_credentialless, + context_require_corp, + corp_cross_origin, + "include", + "retrieved"); + +cacheStorageTest(`[${environment}] require_corp => unsafe-none`, + context_require_corp, + context_none, + corp_cross_origin, + "include", + "retrieved"); +cacheStorageTest(`[${environment}] require_corp => credentialless`, + context_require_corp, + context_credentialless, + corp_cross_origin, + "include", + "retrieved"); +cacheStorageTest(`[${environment}] require_corp => require-corp`, + context_require_corp, + context_require_corp, + corp_cross_origin, + "include", + "retrieved"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache.window.js new file mode 100644 index 0000000000..7d961804a0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cache.window.js @@ -0,0 +1,84 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +// With COEP:credentialless, requesting a resource without credentials MUST NOT +// return a response requested with credentials. This would be a security +// issue, since COEP:credentialless can be used to enable crossOriginIsolation. +// +// The test the behavior of the HTTP cache: +// 1. b.com stores cookie. +// 2. a.com(COEP:unsafe-none): request b.com's resource. +// 3. a.com(COEP:credentialless): request b.com's resource. +// +// The first time, the resource is requested with credentials. The response is +// served with Cache-Control: max-age=31536000. It enters the cache. +// The second time, the resource is requested without credentials. The response +// in the cache must not be returned. + +const cookie_key = "coep_cache_key"; +const cookie_value = "coep_cache_value"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +const GetCookie = (response) => { + return parseCookies(JSON.parse(response))[cookie_key]; +} + +// "same_origin" document with COEP:unsafe-none. +const w_coep_none_token = token(); +const w_coep_none_url = same_origin + executor_path + coep_none + + `&uuid=${w_coep_none_token}` +const w_coep_none = window.open(w_coep_none_url); +add_completion_callback(() => w_coep_none.close()); + +// "same_origin" document with COEP:credentialles. +const w_coep_credentialless_token = token(); +const w_coep_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_coep_credentialless_token}` +const w_coep_credentialless = window.open(w_coep_credentialless_url); +add_completion_callback(() => w_coep_credentialless.close()); + +const this_token = token(); + +// A request toward a "cross-origin" cacheable response. +const request_token = token(); +const request_url = cacheableShowRequestHeaders(cross_origin, request_token); + +promise_setup(async test => { + await setCookie(cross_origin, cookie_key, cookie_value + cookie_same_site_none); +}, "Set cookie"); + +// The "same-origin" COEP:unsafe-none document fetchs a "cross-origin" +// resource. The request is sent with credentials. +promise_setup(async test => { + send(w_coep_none_token, ` + await fetch("${request_url}", { + mode : "no-cors", + credentials: "include", + }); + send("${this_token}", "Resource fetched"); + `); + + assert_equals(await receive(this_token), "Resource fetched"); + assert_equals(await receive(request_token).then(GetCookie), cookie_value); +}, "Cache a response requested with credentials"); + +// The "same-origin" COEP:credentialless document fetches the same resource +// without credentials. The HTTP cache must not be used. Instead a second +// request must be made without credentials. +promise_test(async test => { + send(w_coep_credentialless_token, ` + await fetch("${request_url}", { + mode : "no-cors", + credentials: "include", + }); + send("${this_token}", "Resource fetched"); + `); + + assert_equals(await receive(this_token), "Resource fetched"); + + test.step_timeout(test.unreached_func("The HTTP cache has been used"), 1500); + assert_equals(await receive(request_token).then(GetCookie), undefined); +}, "The HTTP cache must not be used"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cross-origin-isolated.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cross-origin-isolated.window.js new file mode 100644 index 0000000000..361739f283 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/cross-origin-isolated.window.js @@ -0,0 +1,49 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +const http = get_host_info().HTTP_ORIGIN; +const https = get_host_info().HTTPS_ORIGIN; + +let crossOriginIsolatedTest = ( + description, + origin , + headers, + expect_crossOriginIsolated) => { + promise_test_parallel(async test => { + const w_token = token(); + const w_url = origin + executor_path + headers + `&uuid=${w_token}`; + const w = window.open(w_url) + add_completion_callback(() => w.close()); + + const this_token = token(); + send(w_token, ` + if (window.crossOriginIsolated) + send("${this_token}", "crossOriginIsolated"); + else + send("${this_token}", "not isolated") + `); + assert_equals(await receive(this_token), expect_crossOriginIsolated); + }, description); +} + +crossOriginIsolatedTest("Main crossOriginIsolated case:", + https, coop_same_origin + + coep_credentialless, "crossOriginIsolated"); + +crossOriginIsolatedTest("Missing HTTPS:", + http, coop_same_origin + + coep_credentialless, "not isolated"); + +crossOriginIsolatedTest("Missing COOP:same-origin:", + https, coep_credentialless, "not isolated"); + +crossOriginIsolatedTest("Report-only:", + https, coop_same_origin + + coep_report_only_credentialless, "not isolated"); + +crossOriginIsolatedTest("Report-only + enforced:", + https, coop_same_origin + + coep_credentialless + + coep_report_only_credentialless, "crossOriginIsolated"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js new file mode 100644 index 0000000000..780780565f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js @@ -0,0 +1,123 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "credentialless_dedicated_worker"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +promise_test(async test => { + + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + let GetCookie = (response) => { + const headers_credentialless = JSON.parse(response); + return parseCookies(headers_credentialless)[cookie_key]; + } + + const dedicatedWorkerTest = function( + description, origin, coep_for_worker, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async t => { + // Create workers for both window. + const worker_token_1 = token(); + const worker_token_2 = token(); + + // Used to check for errors creating the DedicatedWorker. + const worker_error_1 = token(); + const worker_error_2 = token(); + + const w_worker_src_1 = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${worker_token_1}`; + send(w_control_token, ` + new Worker("${w_worker_src_1}", {}); + worker.onerror = () => { + send("${worker_error_1}", "Worker blocked"); + } + `); + + const w_worker_src_2 = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${worker_token_2}`; + send(w_credentialless_token, ` + const worker = new Worker("${w_worker_src_2}", {}); + worker.onerror = () => { + send("${worker_error_2}", "Worker blocked"); + } + `); + + // Fetch resources with the workers. + const request_token_1 = token(); + const request_token_2 = token(); + const request_url_1 = showRequestHeaders(origin, request_token_1); + const request_url_2 = showRequestHeaders(origin, request_token_2); + + send(worker_token_1, ` + fetch("${request_url_1}", {mode: 'no-cors', credentials: 'include'}) + `); + send(worker_token_2, ` + fetch("${request_url_2}", {mode: 'no-cors', credentials: 'include'}); + `); + + const response_control = await Promise.race([ + receive(worker_error_1), + receive(request_token_1).then(GetCookie) + ]); + assert_equals(response_control, + expected_cookies_control, + "coep:none => "); + + const response_credentialless = await Promise.race([ + receive(worker_error_2), + receive(request_token_2).then(GetCookie) + ]); + assert_equals(response_credentialless, + expected_cookies_credentialless, + "coep:credentialless => "); + }, `fetch ${description}`) + }; + + dedicatedWorkerTest("same-origin + credentialless worker", + same_origin, coep_credentialless, + cookie_same_origin, + cookie_same_origin); + + dedicatedWorkerTest("same-origin", + same_origin, coep_none, + cookie_same_origin, + "Worker blocked"); + + dedicatedWorkerTest("cross-origin", + cross_origin, coep_none, + cookie_cross_origin, + "Worker blocked"); + + dedicatedWorkerTest("cross-origin + credentialless worker", + cross_origin, coep_credentialless, + undefined, + undefined); +}) diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js new file mode 100644 index 0000000000..6ea94d0a19 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js @@ -0,0 +1,127 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +promise_test(async test => { + const same_origin = get_host_info().HTTPS_ORIGIN; + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const cookie_key = "coep_credentialless_fetch"; + const cookie_same_origin = "same_origin"; + const cookie_cross_origin = "cross_origin"; + + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + const fetchTest = function( + description, origin, mode, credentials, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async test => { + const token_1 = token(); + const token_2 = token(); + + send(w_control_token, ` + fetch("${showRequestHeaders(origin, token_1)}", { + mode:"${mode}", + credentials: "${credentials}", + }); + `); + send(w_credentialless_token, ` + fetch("${showRequestHeaders(origin, token_2)}", { + mode:"${mode}", + credentials: "${credentials}", + }); + `); + + const headers_control = JSON.parse(await receive(token_1)); + const headers_credentialless = JSON.parse(await receive(token_2)); + + assert_equals(parseCookies(headers_control)[cookie_key], + expected_cookies_control, + "coep:none => "); + assert_equals(parseCookies(headers_credentialless)[cookie_key], + expected_cookies_credentialless, + "coep:credentialless => "); + }, `fetch ${description}`) + }; + + // Cookies are never sent with credentials='omit' + fetchTest("same-origin + no-cors + credentials:omit", + same_origin, 'no-cors', 'omit', + undefined, + undefined); + fetchTest("same-origin + cors + credentials:omit", + same_origin, 'cors', 'omit', + undefined, + undefined); + fetchTest("cross-origin + no-cors + credentials:omit", + cross_origin, 'no-cors', 'omit', + undefined, + undefined); + fetchTest("cross-origin + cors + credentials:omit", + cross_origin, 'cors', 'omit', + undefined, + undefined); + + // Same-origin request contains Cookies. + fetchTest("same-origin + no-cors + credentials:include", + same_origin, 'no-cors', 'include', + cookie_same_origin, + cookie_same_origin); + fetchTest("same-origin + cors + credentials:include", + same_origin, 'cors', 'include', + cookie_same_origin, + cookie_same_origin); + fetchTest("same-origin + no-cors + credentials:same-origin", + same_origin, 'no-cors', 'same-origin', + cookie_same_origin, + cookie_same_origin); + fetchTest("same-origin + cors + credentials:same-origin", + same_origin, 'cors', 'same-origin', + cookie_same_origin, + cookie_same_origin); + + // Cross-origin CORS requests contains Cookies, if credentials mode is set to + // 'include'. This does not depends on COEP. + fetchTest("cross-origin + cors + credentials:include", + cross_origin, 'cors', 'include', + cookie_cross_origin, + cookie_cross_origin); + fetchTest("cross-origin + cors + same-origin-credentials", + cross_origin, 'cors', 'same-origin', + undefined, + undefined); + + // Cross-origin no-CORS requests includes Cookies when: + // 1. credentials mode is 'include' + // 2. COEP: is not credentialless. + fetchTest("cross-origin + no-cors + credentials:include", + cross_origin, 'no-cors', 'include', + cookie_cross_origin, + undefined); + + fetchTest("cross-origin + no-cors + credentials:same-origin", + cross_origin, 'no-cors', 'same-origin', + undefined, + undefined); +}, ""); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-credentialless.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-credentialless.https.window.js new file mode 100644 index 0000000000..f9d9fcb932 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-credentialless.https.window.js @@ -0,0 +1,37 @@ +// META: variant=?1-4 +// META: variant=?5-9 +// META: variant=?9-last +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +// META: script=./resources/iframeTest.js +// META: script=/common/subset-tests.js + +const parent_coep_credentialless = newWindow(coep_credentialless); +subsetTest(iframeTest, "COEP:credentialless embeds same-origin COEP:none", + parent_coep_credentialless, same_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:credentialless embeds cross-origin COEP:none", + parent_coep_credentialless, cross_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:credentialless embeds same-origin COEP:credentialless", + parent_coep_credentialless, same_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:credentialless embeds cross-origin COEP:credentialless", + parent_coep_credentialless, cross_origin, coep_credentialless, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:credentialless embeds same-origin COEP:require-corp", + parent_coep_credentialless, same_origin, coep_require_corp, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:credentialless embeds cross-origin COEP:require-corp", + parent_coep_credentialless, cross_origin, coep_require_corp, EXPECT_BLOCK); + +// Using CORP:cross-origin might unblock previously blocked iframes. +subsetTest(iframeTestCORP, "COEP:credentialless embeds same-origin COEP:none", + parent_coep_credentialless, same_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTestCORP, "COEP:credentialless embeds cross-origin COEP:none", + parent_coep_credentialless, cross_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTestCORP, "COEP:credentialless embeds same-origin COEP:credentialless", + parent_coep_credentialless, same_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:credentialless embeds cross-origin COEP:credentialless", + parent_coep_credentialless, cross_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:credentialless embeds same-origin COEP:require-corp", + parent_coep_credentialless, same_origin, coep_require_corp, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:credentialless embeds cross-origin COEP:require-corp", + parent_coep_credentialless, cross_origin, coep_require_corp, EXPECT_LOAD); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-none.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-none.https.window.js new file mode 100644 index 0000000000..4f50b8d407 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-none.https.window.js @@ -0,0 +1,22 @@ +// META: variant=?1-4 +// META: variant=?5-last +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +// META: script=./resources/iframeTest.js +// META: script=/common/subset-tests.js + +const parent_coep_none = newWindow(coep_none); +subsetTest(iframeTest, "COEP:none embeds same-origin COEP:none", + parent_coep_none, same_origin, coep_none, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:none embeds cross-origin COEP:none", + parent_coep_none, cross_origin, coep_none, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:none embeds same-origin COEP:credentialless", + parent_coep_none, same_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:none embeds cross-origin COEP:credentialless", + parent_coep_none, cross_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:none embeds same-origin COEP:require-corp", + parent_coep_none, same_origin, coep_require_corp, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:none embeds cross-origin COEP:require-corp", + parent_coep_none, cross_origin, coep_require_corp, EXPECT_LOAD); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-require-corp.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-require-corp.https.window.js new file mode 100644 index 0000000000..a70d4ff8fc --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe-coep-require-corp.https.window.js @@ -0,0 +1,38 @@ +// META: variant=?1-4 +// META: variant=?5-9 +// META: variant=?9-last +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +// META: script=./resources/iframeTest.js +// META: script=/common/subset-tests.js + +const parent_coep_require_corp = newWindow(coep_require_corp); + +subsetTest(iframeTest, "COEP:require-corp embeds same-origin COEP:none", + parent_coep_require_corp, same_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:require-corp embeds cross-origin COEP:none", + parent_coep_require_corp, cross_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:require-corp embeds same-origin COEP:credentialless", + parent_coep_require_corp, same_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:require-corp embeds cross-origin COEP:credentialless", + parent_coep_require_corp, cross_origin, coep_credentialless, EXPECT_BLOCK); +subsetTest(iframeTest, "COEP:require-corp embeds same-origin COEP:require-corp", + parent_coep_require_corp, same_origin, coep_require_corp, EXPECT_LOAD); +subsetTest(iframeTest, "COEP:require-corp embeds cross-origin COEP:require-corp", + parent_coep_require_corp, cross_origin, coep_require_corp, EXPECT_BLOCK); + +// Using CORP:cross-origin might unblock previously blocked iframes. +subsetTest(iframeTestCORP, "COEP:require-corp embeds same-origin COEP:none", + parent_coep_require_corp, same_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTestCORP, "COEP:require-corp embeds cross-origin COEP:none", + parent_coep_require_corp, cross_origin, coep_none, EXPECT_BLOCK); +subsetTest(iframeTestCORP, "COEP:require-corp embeds same-origin COEP:credentialless", + parent_coep_require_corp, same_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:require-corp embeds cross-origin COEP:credentialless", + parent_coep_require_corp, cross_origin, coep_credentialless, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:require-corp embeds same-origin COEP:require-corp", + parent_coep_require_corp, same_origin, coep_require_corp, EXPECT_LOAD); +subsetTest(iframeTestCORP, "COEP:require-corp embeds cross-origin COEP:require-corp", + parent_coep_require_corp, cross_origin, coep_require_corp, EXPECT_LOAD); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe.window.js new file mode 100644 index 0000000000..d7a9c1e170 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/iframe.window.js @@ -0,0 +1,47 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "coep_redirect"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +// Operate on a window with COEP:credentialless. +const w_token = token(); +const w_url = same_origin + executor_path + coep_credentialless + + `&uuid=${w_token}` +const w = window.open(w_url); +add_completion_callback(() => w.close()); + +// Check whether COEP:credentialless applies to navigation request. It +// shouldn't. +const iframeTest = function(name, origin, expected_cookies) { + promise_test_parallel(async test => { + const token_request = token(); + const url = showRequestHeaders(origin, token_request); + + send(w_token, ` + const iframe = document.createElement("iframe"); + iframe.src = "${url}"; + document.body.appendChild(iframe); + `); + + const headers = JSON.parse(await receive(token_request)); + assert_equals(parseCookies(headers)[cookie_key], expected_cookies); + }, name) +}; + +promise_test_parallel(async test => { + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + iframeTest("same-origin", same_origin, cookie_same_origin); + iframeTest("cross-origin", cross_origin, cookie_cross_origin); +}, "Setup"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/image.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/image.https.window.js new file mode 100644 index 0000000000..2e9166d1bb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/image.https.window.js @@ -0,0 +1,97 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +promise_test_parallel(async test => { + const same_origin = get_host_info().HTTPS_ORIGIN; + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const cookie_key = "coep_credentialless_image"; + const cookie_same_origin = "same_origin"; + const cookie_cross_origin = "cross_origin"; + + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + let imgTest = function( + description, origin, mode, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async test => { + const token_1 = token(); + const token_2 = token(); + + send(w_control_token, ` + let img = document.createElement("img"); + img.src = "${showRequestHeaders(origin, token_1)}"; + ${mode}; + document.body.appendChild(img); + `); + send(w_credentialless_token, ` + let img = document.createElement("img"); + img.src = "${showRequestHeaders(origin, token_2)}"; + ${mode}; + document.body.appendChild(img); + `); + + const headers_control = JSON.parse(await receive(token_1)); + const headers_credentialless = JSON.parse(await receive(token_2)); + + assert_equals(parseCookies(headers_control)[cookie_key], + expected_cookies_control, + "coep:none => "); + assert_equals(parseCookies(headers_credentialless)[cookie_key], + expected_cookies_credentialless, + "coep:credentialless => "); + }, `image ${description}`) + }; + + // Same-origin request always contains Cookies: + imgTest("same-origin + undefined", + same_origin, '', + cookie_same_origin, + cookie_same_origin); + imgTest("same-origin + anonymous", + same_origin, 'img.crossOrigin="anonymous"', + cookie_same_origin, + cookie_same_origin); + imgTest("same-origin + use-credentials", + same_origin, 'img.crossOrigin="use-credentials"', + cookie_same_origin, + cookie_same_origin); + + // Cross-origin request contains cookies in the following cases: + // - COEP:credentialless is not set. + // - img.crossOrigin is `use-credentials`. + imgTest("cross-origin + undefined", + cross_origin, '', + cookie_cross_origin, + undefined); + imgTest("cross-origin + anonymous", + cross_origin, 'img.crossOrigin="anonymous"', + undefined, + undefined); + imgTest("cross-origin + use-credentials", + cross_origin, 'img.crossOrigin="use-credentials"', + cookie_cross_origin, + cookie_cross_origin); +}, "Main"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/link.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/link.https.window.js new file mode 100644 index 0000000000..0a0f8eef66 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/link.https.window.js @@ -0,0 +1,99 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +promise_test_parallel(async test => { + const same_origin = get_host_info().HTTPS_ORIGIN; + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const cookie_key = "coep_credentialless_link"; + const cookie_same_origin = "same_origin"; + const cookie_cross_origin = "cross_origin"; + + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + let linkTest = function( + description, origin, mode, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async test => { + const token_1 = token(); + const token_2 = token(); + + send(w_control_token, ` + let link = document.createElement("link"); + link.href = "${showRequestHeaders(origin, token_1)}"; + link.rel = "stylesheet"; + ${mode} + document.head.appendChild(link); + `); + send(w_credentialless_token, ` + let link = document.createElement("link"); + link.href = "${showRequestHeaders(origin, token_2)}"; + link.rel = "stylesheet"; + ${mode} + document.head.appendChild(link); + `); + + const headers_control = JSON.parse(await receive(token_1)); + const headers_credentialless = JSON.parse(await receive(token_2)); + + assert_equals(parseCookies(headers_control)[cookie_key], + expected_cookies_control, + "coep:none => "); + assert_equals(parseCookies(headers_credentialless)[cookie_key], + expected_cookies_credentialless, + "coep:credentialless => "); + }, `link ${description}`) + }; + + // Same-origin request always contains Cookies: + linkTest("same-origin + undefined", + same_origin, '', + cookie_same_origin, + cookie_same_origin); + linkTest("same-origin + anonymous", + same_origin, 'link.crossOrigin="anonymous"', + cookie_same_origin, + cookie_same_origin); + linkTest("same-origin + use-credentials", + same_origin, 'link.crossOrigin="use-credentials"', + cookie_same_origin, + cookie_same_origin); + + // Cross-origin request contains cookies in the following cases: + // - COEP:credentialless is not set. + // - link.crossOrigin is `use-credentials`. + linkTest("cross-origin + undefined", + cross_origin, '', + cookie_cross_origin, + undefined); + linkTest("cross-origin + anonymous", + cross_origin, 'link.crossOrigin="anonymous"', + undefined, + undefined); + linkTest("cross-origin + use-credentials", + cross_origin, 'link.crossOrigin="use-credentials"', + cookie_cross_origin, + cookie_cross_origin); +}, "Main"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/redirect.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/redirect.window.js new file mode 100644 index 0000000000..db8ca08d36 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/redirect.window.js @@ -0,0 +1,55 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "coep_redirect"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +// Operate on a window with COEP:credentialless.: +const w_token = token(); +const w_url = same_origin + executor_path + coep_credentialless + + `&uuid=${w_token}` +const w = window.open(w_url); +add_completion_callback(() => w.close()); + +let redirectTest = function(name, + redirect_origin, + final_origin, + expected_cookies) { + promise_test_parallel(async test => { + const token_request = token(); + const url = redirect_origin + "/common/redirect.py?location=" + + encodeURIComponent(showRequestHeaders(final_origin, token_request)); + + send(w_token, ` + const img = document.createElement("img"); + img.src = "${url}"; + document.body.appendChild(img); + `); + + const headers = JSON.parse(await receive(token_request)); + assert_equals(parseCookies(headers)[cookie_key], expected_cookies); + }, name) +}; + +promise_test_parallel(async test => { + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + redirectTest("same-origin -> same-origin", + same_origin, same_origin, cookie_same_origin); + redirectTest("same-origin -> cross-origin", + same_origin, cross_origin, undefined) + redirectTest("cross-origin -> same-origin", + cross_origin, same_origin, undefined); + redirectTest("cross-origin -> cross-origin", + cross_origin, cross_origin, undefined); +}, "Setup"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-navigation.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-navigation.https.window.js new file mode 100644 index 0000000000..1d62996e38 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-navigation.https.window.js @@ -0,0 +1,139 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=./resources/common.js +const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); +const COEP = '|header(cross-origin-embedder-policy,credentialless)'; +const COEP_RO = + '|header(cross-origin-embedder-policy-report-only,credentialless)'; +const CORP_CROSS_ORIGIN = + '|header(cross-origin-resource-policy,cross-origin)'; +const FRAME_URL = `${ORIGIN}/common/blank.html?pipe=`; +const REMOTE_FRAME_URL = `${REMOTE_ORIGIN}/common/blank.html?pipe=`; + +function checkCorpReport(report, contextUrl, blockedUrl, disposition) { + assert_equals(report.type, 'coep'); + assert_equals(report.url, contextUrl); + assert_equals(report.body.type, 'corp'); + assert_equals(report.body.blockedURL, blockedUrl); + assert_equals(report.body.disposition, disposition); + assert_equals(report.body.destination, 'iframe'); +} + +function checkCoepMismatchReport(report, contextUrl, blockedUrl, disposition) { + assert_equals(report.type, 'coep'); + assert_equals(report.url, contextUrl); + assert_equals(report.body.type, 'navigation'); + assert_equals(report.body.blockedURL, blockedUrl); + assert_equals(report.body.disposition, disposition); +} + +function loadFrame(document, url) { + return new Promise((resolve, reject) => { + const frame = document.createElement('iframe'); + frame.src = url; + frame.onload = () => resolve(frame); + frame.onerror = reject; + document.body.appendChild(frame); + }); +} + +// |parentSuffix| is a suffix for the parent frame URL. +// |targetUrl| is a URL for the target frame. +async function loadFrames(test, parentSuffix, targetUrl) { + const frame = await loadFrame(document, FRAME_URL + parentSuffix); + test.add_cleanup(() => frame.remove()); + // Here we don't need "await". This loading may or may not succeed, and + // we're not interested in the result. + loadFrame(frame.contentDocument, targetUrl); + + return frame; +} + +async function observeReports(global, expected_count) { + const reports = []; + const receivedEveryReports = new Promise(resolve => { + if (expected_count == 0) + resolve(); + + const observer = new global.ReportingObserver((rs) => { + for (const r of rs) { + reports.push(r.toJSON()); + } + if (expected_count <= reports.length) + resolve(); + }); + observer.observe(); + + }); + + // Wait 500ms more to catch additionnal unexpected reports. + await receivedEveryReports; + await new Promise(r => step_timeout(r, 500)); + return reports; +} + +function desc(headers) { + return headers === '' ? '(none)' : headers; +} + +// CASES is a list of test case. Each test case consists of: +// parent_headers: the suffix of the URL of the parent frame. +// target_headers: the suffix of the URL of the target frame. +// expected_reports: one of: +// 'CORP': CORP violation +// 'CORP-RO': CORP violation (report only) +// 'NAV': COEP mismatch between the frames. +// 'NAV-RO': COEP mismatch between the frames (report only). +const reportingTest = function( + parent_headers, target_headers, expected_reports) { + // These tests are very slow, so they must be run in parallel using + // async_test. + promise_test_parallel(async t => { + const targetUrl = REMOTE_FRAME_URL + target_headers; + const parent = await loadFrames(t, parent_headers, targetUrl); + const contextUrl = parent.src ? parent.src : 'about:blank'; + const reports = await observeReports( + parent.contentWindow, + expected_reports.length + ); + assert_equals(reports.length, expected_reports.length); + for (let i = 0; i < reports.length; i += 1) { + const report = reports[i]; + switch (expected_reports[i]) { + case 'CORP': + checkCorpReport(report, contextUrl, targetUrl, 'enforce'); + break; + case 'CORP-RO': + checkCorpReport(report, contextUrl, targetUrl, 'reporting'); + break; + case 'NAV': + checkCoepMismatchReport(report, contextUrl, targetUrl, 'enforce'); + break; + case 'NAV-RO': + checkCoepMismatchReport(report, contextUrl, targetUrl, 'reporting'); + break; + default: + assert_unreached( + 'Unexpected report exception: ' + expected_reports[i]); + } + } + }, `parent: ${desc(parent_headers)}, target: ${desc(target_headers)}, `); +} + +reportingTest('', '', []); +reportingTest('', COEP, []); +reportingTest(COEP, COEP, ['CORP']); +reportingTest(COEP, '', ['CORP']); + +reportingTest('', CORP_CROSS_ORIGIN, []); +reportingTest(COEP, CORP_CROSS_ORIGIN, ['NAV']); + +reportingTest('', COEP + CORP_CROSS_ORIGIN, []); +reportingTest(COEP, COEP + CORP_CROSS_ORIGIN, []); + +reportingTest(COEP_RO, COEP, ['CORP-RO']); +reportingTest(COEP_RO, '', ['CORP-RO', 'NAV-RO']); +reportingTest(COEP_RO, CORP_CROSS_ORIGIN, ['NAV-RO']); +reportingTest(COEP_RO, COEP + CORP_CROSS_ORIGIN, []); + +reportingTest(COEP, COEP_RO + CORP_CROSS_ORIGIN, ['NAV']); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js new file mode 100644 index 0000000000..ab583fd49e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js @@ -0,0 +1,74 @@ +// META: timeout=long +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js +const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); +const BASE = "/html/cross-origin-embedder-policy/resources"; +const REPORTING_FRAME_URL = `${ORIGIN}${BASE}/reporting-empty-frame.html` + + '?pipe=header(cross-origin-embedder-policy,credentialless)' + + '&token=${token()}'; + +async function observeReports(global, expected_count) { + const reports = []; + const receivedEveryReports = new Promise(resolve => { + if (expected_count == 0) + resolve(); + + const observer = new global.ReportingObserver((rs) => { + for (const r of rs) { + reports.push(r.toJSON()); + } + if (expected_count <= reports.length) + resolve(); + }); + observer.observe(); + + }); + + await receivedEveryReports; + // Wait 1000ms more to catch additionnal unexpected reports. + await new Promise(r => step_timeout(r, 1000)); + return reports; +} + +async function fetchInFrame(t, frameUrl, url, expected_count) { + const frame = await with_iframe(frameUrl); + t.add_cleanup(() => frame.remove()); + + const init = { mode: 'no-cors', cache: 'no-store' }; + let future_reports = observeReports(frame.contentWindow, expected_count); + await frame.contentWindow.fetch(url, init).catch(() => {}); + + return await future_reports; +} + +function checkReport(report, contextUrl, blockedUrl, disposition, destination) { + assert_equals(report.type, 'coep'); + assert_equals(report.url, contextUrl); + assert_equals(report.body.type, 'corp'); + assert_equals(report.body.blockedURL, blockedUrl); + assert_equals(report.body.disposition, disposition); + assert_equals(report.body.destination, destination); +} + +// A redirection is used, so that the initial request is same-origin and is +// proxyied through the service worker. The ServiceWorker is COEP:unsafe-none, +// so it will make the cross-origin request with credentials. The fetch will +// succeed, but the response will be blocked by CORP when entering the +// COEP:credentialless document. +// https://github.com/w3c/ServiceWorker/issues/1592 +promise_test(async (t) => { + const url = `${ORIGIN}/common/redirect.py?location=` + + encodeURIComponent(`${REMOTE_ORIGIN}/common/text-plain.txt`); + const WORKER_URL = `${ORIGIN}${BASE}/sw.js`; + const reg = await service_worker_unregister_and_register( + t, WORKER_URL, REPORTING_FRAME_URL); + t.add_cleanup(() => reg.unregister()); + const worker = reg.installing || reg.waiting || reg.active; + worker.addEventListener('error', t.unreached_func('Worker.onerror')); + await wait_for_state(t, worker, 'activated'); + + const reports = await fetchInFrame(t, REPORTING_FRAME_URL, url, 1); + assert_equals(reports.length, 1); + checkReport(reports[0], REPORTING_FRAME_URL, url, 'enforce', ''); +}); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/common.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/common.js new file mode 100644 index 0000000000..ce21c766f6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/common.js @@ -0,0 +1,134 @@ +const executor_path = '/common/dispatcher/executor.html?pipe='; +const executor_worker_path = '/common/dispatcher/executor-worker.js?pipe='; +const executor_service_worker_path = '/common/dispatcher/executor-service-worker.js?pipe='; + +// COEP +const coep_none = + '|header(Cross-Origin-Embedder-Policy,none)'; +const coep_credentialless = + '|header(Cross-Origin-Embedder-Policy,credentialless)'; +const coep_require_corp = + '|header(Cross-Origin-Embedder-Policy,require-corp)'; + +// COEP-Report-Only +const coep_report_only_credentialless = + '|header(Cross-Origin-Embedder-Policy-Report-Only,credentialless)'; + +// COOP +const coop_same_origin = + '|header(Cross-Origin-Opener-Policy,same-origin)'; + +// CORP +const corp_cross_origin = + '|header(Cross-Origin-Resource-Policy,cross-origin)'; + +const cookie_same_site_none = ';SameSite=None;Secure'; + +// Test using the modern async/await primitives are easier to read/write. +// However they run sequentially, contrary to async_test. This is the parallel +// version, to avoid timing out. +let promise_test_parallel = (promise, description) => { + async_test(test => { + promise(test) + .then(() => test.done()) + .catch(test.step_func(error => { throw error; })); + }, description); +}; + +// Add a cookie |cookie_key|=|cookie_value| on an |origin|. +// Note: cookies visibility depends on the path of the document. Those are set +// from a document from: /html/cross-origin-embedder-policy/credentialless/. So +// the cookie is visible to every path underneath. +const setCookie = async (origin, cookie_key, cookie_value) => { + const popup_token = token(); + const popup_url = origin + executor_path + `&uuid=${popup_token}`; + const popup = window.open(popup_url); + + const reply_token = token(); + send(popup_token, ` + document.cookie = "${cookie_key}=${cookie_value}"; + send("${reply_token}", "done"); + `); + assert_equals(await receive(reply_token), "done"); + popup.close(); +} + +let parseCookies = function(headers_json) { + if (!headers_json["cookie"]) + return {}; + + return headers_json["cookie"] + .split(';') + .map(v => v.split('=')) + .reduce((acc, v) => { + acc[v[0].trim()] = v[1].trim(); + return acc; + }, {}); +} + +// Open a new window with a given |origin|, loaded with COEP:credentialless. The +// new document will execute any scripts sent toward the token it returns. +const newCredentiallessWindow = (origin) => { + const main_document_token = token(); + const url = origin + executor_path + coep_credentialless + + `&uuid=${main_document_token}`; + const context = window.open(url); + add_completion_callback(() => w.close()); + return main_document_token; +}; + +// Create a new iframe, loaded with COEP:credentialless. +// The new document will execute any scripts sent toward the token it returns. +const newCredentiallessIframe = (parent_token, child_origin) => { + const sub_document_token = token(); + const iframe_url = child_origin + executor_path + coep_credentialless + + `&uuid=${sub_document_token}`; + send(parent_token, ` + let iframe = document.createElement("iframe"); + iframe.src = "${iframe_url}"; + document.body.appendChild(iframe); + `) + return sub_document_token; +}; + +// A common interface for building the 4 type of execution contexts: +// It outputs: [ +// - The token to communicate with the environment. +// - A promise resolved when the environment encounters an error. +// ] +const environments = { + document: headers => { + const tok = token(); + const url = window.origin + executor_path + headers + `&uuid=${tok}`; + const context = window.open(url); + add_completion_callback(() => context.close()); + return [tok, new Promise(resolve => {})]; + }, + + dedicated_worker: headers => { + const tok = token(); + const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`; + const context = new Worker(url); + return [tok, new Promise(resolve => context.onerror = resolve)]; + }, + + shared_worker: headers => { + const tok = token(); + const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`; + const context = new SharedWorker(url); + return [tok, new Promise(resolve => context.onerror = resolve)]; + }, + + service_worker: headers => { + const tok = token(); + const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`; + const scope = url; // Generate a one-time scope for service worker. + const error = new Promise(resolve => { + navigator.serviceWorker.register(url, {scope: scope}) + .then(registration => { + add_completion_callback(() => registration.unregister()); + }, /* catch */ resolve); + }); + return [tok, error]; + }, +}; diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/iframeTest.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/iframeTest.js new file mode 100644 index 0000000000..501a864d46 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/iframeTest.js @@ -0,0 +1,85 @@ +// One document embeds another in an iframe. Both are loaded from the network. +// Depending on the response headers: +// - Cross-Origin-Embedder-Policy (COEP) +// - Cross-Origin-Resource-Policy (CORP) +// The child must load or must be blocked. +// +// What to do for: +// - COEP:credentialless +// - COEP:credentialless-on-children +// is currently an active open question. This test will be updated/completed +// later. + +// There are no interoperable ways to check an iframe failed to load. So a +// timeout is being used. See https://github.com/whatwg/html/issues/125 +// Moreover, we want to track progress, managing timeout explicitly allows to +// get a per-test results, even in case of failure of one. +setup({ explicit_timeout: true }); + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +// Open a new window loaded with the given |headers|. The new document will +// execute any script sent toward the token it returns. +const newWindow = (headers) => { + const executor_token = token(); + const url = same_origin + executor_path + headers + `&uuid=${executor_token}`; + const w = window.open(url); + add_completion_callback(() => w.close()); + return executor_token; +}; + +const EXPECT_LOAD = "load"; +const EXPECT_BLOCK = "block"; + +// Load in iframe. Control both the parent and the child headers. Check whether +// it loads or not. +const iframeTest = function( + description, + parent_token, + child_origin, + child_headers, + expectation +) { + promise_test_parallel(async test => { + const test_token = token(); + + const child_token = token(); + const child_url = child_origin + executor_path + child_headers + + `&uuid=${child_token}`; + + await send(parent_token, ` + let iframe = document.createElement("iframe"); + iframe.src = "${child_url}"; + document.body.appendChild(iframe); + `); + + await send(child_token, ` + send("${test_token}", "load"); + `); + + // There are no interoperable ways to check an iframe failed to load. So a + // timeout is being used. + // See https://github.com/whatwg/html/issues/125 + // Use a shorter timeout when it is expected to be reached. + // - The long delay reduces the false-positive rate. False-positive causes + // stability problems on bot, so a big delay is used to vanish them. + // https://crbug.com/1215956. + // - The short delay avoids delaying too much the test(s) for nothing and + // timing out. False-negative are not a problem, they just need not to + // overwhelm the true-negative, which is trivial to get. + step_timeout(()=>send(test_token, "block"), expectation == EXPECT_BLOCK + ? 2000 + : 6000 + ); + + assert_equals(await receive(test_token), expectation); + }, description); +} + +// A decorated version of iframeTest, adding CORP:cross-origin to the child. +const iframeTestCORP = function() { + arguments[0] += ", CORP:cross-origin"; // description + arguments[3] += corp_cross_origin; // child_headers + iframeTest(...arguments); +} diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/script.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/script.https.window.js new file mode 100644 index 0000000000..96bf7b08db --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/script.https.window.js @@ -0,0 +1,99 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +window.onload = function() { + promise_test_parallel(async test => { + const same_origin = get_host_info().HTTPS_ORIGIN; + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const cookie_key = "coep_credentialless_script"; + const cookie_same_origin = "same_origin"; + const cookie_cross_origin = "cross_origin"; + + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + let scriptTest = function( + description, origin, mode, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async test => { + const token_1 = token(); + const token_2 = token(); + + send(w_control_token, ` + let script = document.createElement("script"); + script.src = "${showRequestHeaders(origin, token_1)}"; + ${mode}; + document.body.appendChild(script); + `); + send(w_credentialless_token, ` + let script = document.createElement("script"); + script.src = "${showRequestHeaders(origin, token_2)}"; + ${mode}; + document.body.appendChild(script); + `); + + const headers_control = JSON.parse(await receive(token_1)); + const headers_credentialless = JSON.parse(await receive(token_2)); + + assert_equals(parseCookies(headers_control)[cookie_key], + expected_cookies_control, + "coep:none => "); + assert_equals(parseCookies(headers_credentialless)[cookie_key], + expected_cookies_credentialless, + "coep:credentialless => "); + }, `script ${description}`) + }; + + // Same-origin request always contains Cookies: + scriptTest("same-origin + undefined", + same_origin, '', + cookie_same_origin, + cookie_same_origin); + scriptTest("same-origin + anonymous", + same_origin, 'script.crossOrigin="anonymous"', + cookie_same_origin, + cookie_same_origin); + scriptTest("same-origin + use-credentials", + same_origin, 'script.crossOrigin="use-credentials"', + cookie_same_origin, + cookie_same_origin); + + // Cross-origin request contains cookies in the following cases: + // - COEP:credentialless is not set. + // - script.crossOrigin is `use-credentials`. + scriptTest("cross-origin + undefined", + cross_origin, '', + cookie_cross_origin, + undefined); + scriptTest("cross-origin + anonymous", + cross_origin, 'script.crossOrigin="anonymous"', + undefined, + undefined); + scriptTest("cross-origin + use-credentials", + cross_origin, 'script.crossOrigin="use-credentials"', + cookie_cross_origin, + cookie_cross_origin); + }, "Main"); +} diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-credentialless-proxy.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-credentialless-proxy.https.window.js new file mode 100644 index 0000000000..d1a61dbb57 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-credentialless-proxy.https.window.js @@ -0,0 +1,85 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +promise_test(async test => { + const this_token_1 = token(); + const this_token_2 = token(); + + // Register a COEP:credentialless ServiceWorker. + const sw_token = token(); + const sw_url = + executor_service_worker_path + coep_credentialless + `&uuid=${sw_token}`; + // Executors should be controlled by the service worker. + const scope = executor_path; + const sw_registration = + await service_worker_unregister_and_register(test, sw_url, scope); + test.add_cleanup(() => sw_registration.unregister()); + await wait_for_state(test, sw_registration.installing, 'activated'); + + // Configure the ServiceWorker to proxy the fetch requests. Wait for the + // worker to be installed and activated. + send(sw_token, ` + fetchHandler = event => { + if (!event.request.url.includes("/proxied")) + return; + + send("${this_token_1}", "ServiceWorker: Proxying"); + + // Response with a cross-origin no-cors resource. + const url = "${cross_origin}" + "/common/blank.html}"; + + event.respondWith(new Promise(async resolve => { + try { + let response = await fetch(url, { + mode: "no-cors", + credentials: "include" + }); + send("${this_token_1}", "ServiceWorker: Fetch success"); + resolve(response); + } catch (error) { + send("${this_token_1}", "ServiceWorker: Fetch failure"); + resolve(new Response("", {status: 400})); + } + })); + } + + await clients.claim(); + + send("${this_token_1}", serviceWorker.state); + `) + assert_equals(await receive(this_token_1), "activated"); + + // Create a COEP:credentialless document. + const document_token = environments["document"](coep_credentialless)[0]; + + // The document fetches a same-origin no-cors resource. The requests needs to + // be same-origin to be handled by the ServiceWorker. + send(document_token, ` + try { + const response = await fetch("/proxied", { mode: "no-cors", }); + + send("${this_token_2}", "Document: Fetch success"); + } catch (error) { + send("${this_token_2}", "Document: Fetch error"); + } + `); + + // The COEP:credentialless ServiceWorker is able to handle the cross-origin + // no-cors request, requested with credentials. + assert_equals(await receive(this_token_1), "ServiceWorker: Proxying"); + assert_equals(await receive(this_token_1), "ServiceWorker: Fetch success"); + + // The COEP:credentialless Document is allowed by CORP to get it. + assert_equals(await receive(this_token_2), "Document: Fetch success"); + + // test.add_cleanup doesn't allow waiting for a promise. Unregistering a + // ServiceWorker is an asynchronous operation. It might not be completed on + // time for the next test. Do it here for extra flakiness safety. + await sw_registration.unregister() +}, "COEP:credentialless ServiceWorker"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-none-proxy.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-none-proxy.https.window.js new file mode 100644 index 0000000000..21969bb7ed --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker-coep-none-proxy.https.window.js @@ -0,0 +1,87 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +promise_test(async test => { + const this_token_1 = token(); + const this_token_2 = token(); + + // Register a COEP:none ServiceWorker. + const sw_token = token(); + const sw_url = executor_service_worker_path + coep_none + `&uuid=${sw_token}`; + // Executors should be controlled by the service worker. + const scope = executor_path; + const sw_registration = + await service_worker_unregister_and_register(test, sw_url, scope); + test.add_cleanup(() => sw_registration.unregister()); + await wait_for_state(test, sw_registration.installing, 'activated'); + + // Configure the ServiceWorker to proxy the fetch requests. Wait for the + // worker to be installed and activated. + send(sw_token, ` + fetchHandler = event => { + if (!event.request.url.includes("/proxied")) + return; + + send("${this_token_1}", "ServiceWorker: Proxying"); + + // Response with a cross-origin no-cors resource. + const url = "${cross_origin}" + "/common/blank.html}"; + + event.respondWith(new Promise(async resolve => { + try { + let response = await fetch(url, { + mode: "no-cors", + credentials: "include" + }); + send("${this_token_1}", "ServiceWorker: Fetch success"); + resolve(response); + } catch (error) { + send("${this_token_1}", "ServiceWorker: Fetch failure"); + resolve(new Response("", {status: 400})); + } + })); + } + + await clients.claim(); + + send("${this_token_1}", serviceWorker.state); + `) + assert_equals(await receive(this_token_1), "activated"); + + // Create a COEP:credentialless document. + const document_token = environments["document"](coep_credentialless)[0]; + + // The document fetches a same-origin no-cors resource. The requests needs to + // be same-origin to be handled by the ServiceWorker. + send(document_token, ` + try { + const response = await fetch("/proxied", { + mode: "no-cors", + credentials: "include" + }); + + send("${this_token_2}", "Document: Fetch success"); + } catch (error) { + send("${this_token_2}", "Document: Fetch error"); + } + `); + + // The COEP:unsafe-none ServiceWorker is able to handle the cross-origin + // no-cors request, requested with credentials. + assert_equals(await receive(this_token_1), "ServiceWorker: Proxying"); + assert_equals(await receive(this_token_1), "ServiceWorker: Fetch success"); + + // However, the COEP:credentialless Document is disallowed by CORP to get it. + assert_equals(await receive(this_token_2), "Document: Fetch error"); + + // test.add_cleanup doesn't allow waiting for a promise. Unregistering a + // ServiceWorker is an asynchronous operation. It might not be completed on + // time for the next test. Do it here for extra flakiness safety. + await sw_registration.unregister() +}, "COEP:unsafe-none ServiceWorker"); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker.https.window.js new file mode 100644 index 0000000000..4fc0061c57 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/service-worker.https.window.js @@ -0,0 +1,113 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js +// META: script=./resources/common.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "credentialless_service_worker"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +promise_test(async t => { + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One iframe with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = document.createElement("iframe"); + w_control.src = w_control_url; + document.body.appendChild(w_control); + + // One iframe with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = document.createElement("iframe"); + w_credentialless.src = w_credentialless_url; + document.body.appendChild(w_credentialless); + + const serviceWorkerTest = function( + description, origin, coep_for_worker, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test(async test => { + // Create workers for both window. + const control_worker_token = token(); + const credentialless_worker_token = token(); + + const w_control_worker_src = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${control_worker_token}`; + const w_control_worker_reg = + await service_worker_unregister_and_register( + test, w_control_worker_src, w_control_url); + + const w_credentialless_worker_src = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${credentialless_worker_token}`; + const w_credentialless_worker_reg = + await service_worker_unregister_and_register( + test, w_credentialless_worker_src, w_credentialless_url); + + // Fetch resources from the workers. + const control_request_token = token(); + const credentialless_request_token = token(); + const control_request_url = showRequestHeaders(origin, control_request_token); + const credentialless_request_url = showRequestHeaders(origin, credentialless_request_token); + send(control_worker_token, ` + fetch("${control_request_url}", { + mode: 'no-cors', + credentials: 'include' + }) + `); + send(credentialless_worker_token, ` + fetch("${credentialless_request_url}", { + mode: 'no-cors', + credentials: 'include' + }) + `); + + // Retrieve the resource request headers. + const headers_control = JSON.parse(await receive(control_request_token)); + const headers_credentialless = JSON.parse(await receive(credentialless_request_token)); + + assert_equals(parseCookies(headers_control)[cookie_key], + expected_cookies_control, + "coep:none => "); + assert_equals(parseCookies(headers_credentialless)[cookie_key], + expected_cookies_credentialless, + "coep:credentialless => "); + + w_control_worker_reg.unregister(); + w_credentialless_worker_reg.unregister(); + }, `fetch ${description}`) + }; + + serviceWorkerTest("same-origin", + same_origin, coep_none, + cookie_same_origin, + cookie_same_origin); + + serviceWorkerTest("same-origin + credentialless worker", + same_origin, coep_credentialless, + cookie_same_origin, + cookie_same_origin); + + serviceWorkerTest("cross-origin", + cross_origin, coep_none, + cookie_cross_origin, + cookie_cross_origin); + + serviceWorkerTest("cross-origin + credentialless worker", + cross_origin, coep_credentialless, + undefined, + undefined); +}) diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/shared-worker.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/shared-worker.https.window.js new file mode 100644 index 0000000000..0bfa72e2e5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/shared-worker.https.window.js @@ -0,0 +1,119 @@ +// META: timeout=long +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "credentialless_shared_worker"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +promise_test(async test => { + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); + + // One window with COEP:none. (control) + const w_control_token = token(); + const w_control_url = same_origin + executor_path + + coep_none + `&uuid=${w_control_token}` + const w_control = window.open(w_control_url); + add_completion_callback(() => w_control.close()); + + // One window with COEP:credentialless. (experiment) + const w_credentialless_token = token(); + const w_credentialless_url = same_origin + executor_path + + coep_credentialless + `&uuid=${w_credentialless_token}`; + const w_credentialless = window.open(w_credentialless_url); + add_completion_callback(() => w_credentialless.close()); + + let GetCookie = (response) => { + const headers_credentialless = JSON.parse(response); + return parseCookies(headers_credentialless)[cookie_key]; + } + + const sharedWorkerTest = function( + description, origin, coep_for_worker, + expected_cookies_control, + expected_cookies_credentialless) + { + promise_test_parallel(async t => { + // Create workers for both window. + const worker_token_1 = token(); + const worker_token_2 = token(); + + // Used to check for errors creating the DedicatedWorker. + const worker_error_1 = token(); + const worker_error_2 = token(); + + const w_worker_src_1 = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${worker_token_1}`; + send(w_control_token, ` + let worker = new SharedWorker("${w_worker_src_1}", {}); + worker.onerror = () => { + send("${worker_error_1}", "Worker blocked"); + } + `); + + const w_worker_src_2 = same_origin + executor_worker_path + + coep_for_worker + `&uuid=${worker_token_2}`; + send(w_credentialless_token, ` + let worker = new SharedWorker("${w_worker_src_2}", {}); + worker.onerror = () => { + send("${worker_error_2}", "Worker blocked"); + } + `); + + // Fetch resources with the workers. + const request_token_1 = token(); + const request_token_2 = token(); + const request_url_1 = showRequestHeaders(origin, request_token_1); + const request_url_2 = showRequestHeaders(origin, request_token_2); + send(worker_token_1, + `fetch("${request_url_1}", {mode: 'no-cors', credentials: 'include'})`); + send(worker_token_2, + `fetch("${request_url_2}", {mode: 'no-cors', credentials: 'include'})`); + + const response_control = await Promise.race([ + receive(worker_error_1), + receive(request_token_1).then(GetCookie) + ]); + assert_equals(response_control, + expected_cookies_control, + "coep:none => "); + + const response_credentialless = await Promise.race([ + receive(worker_error_2), + receive(request_token_2).then(GetCookie) + ]); + assert_equals(response_credentialless, + expected_cookies_credentialless, + "coep:credentialless => "); + }, `fetch ${description}`) + }; + + sharedWorkerTest("same-origin", + same_origin, coep_none, + cookie_same_origin, + cookie_same_origin); + + sharedWorkerTest("same-origin + credentialless worker", + same_origin, coep_credentialless, + cookie_same_origin, + cookie_same_origin); + + sharedWorkerTest("cross-origin", + cross_origin, coep_none, + cookie_cross_origin, + cookie_cross_origin); + + sharedWorkerTest("cross-origin + credentialless worker", + cross_origin, coep_credentialless, + undefined, + undefined); +}) diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js new file mode 100644 index 0000000000..0410b48564 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js @@ -0,0 +1,53 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./resources/common.js + +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cookie_key = "coep_credentialless_image"; +const cookie_same_origin = "same_origin"; +const cookie_cross_origin = "cross_origin"; + +promise_setup(async test => { + await Promise.all([ + setCookie(same_origin, cookie_key, cookie_same_origin + + cookie_same_site_none), + setCookie(cross_origin, cookie_key, cookie_cross_origin + + cookie_same_site_none), + ]); +}, "Setup cookies"); + +const videoTest = function(description, origin, mode, expected_cookie) { + promise_test(async test => { + const video_token = token(); + + let video = document.createElement("video"); + video.src = showRequestHeaders(origin, video_token); + video.autoplay = true; + if (mode) + video.crossOrigin = mode; + document.body.appendChild(video); + + const headers = JSON.parse(await receive(video_token)); + + assert_equals(parseCookies(headers)[cookie_key], expected_cookie); + }, `video ${description}`) +}; + +// Same-origin request always contains Cookies: +videoTest("same-origin + undefined", + same_origin, undefined, cookie_same_origin); +videoTest("same-origin + anonymous", + same_origin, 'anonymous', cookie_same_origin); +videoTest("same-origin + use-credentials", + same_origin, 'use-credentials', cookie_same_origin); + +// Cross-origin request contains cookies, only when sent in CORS mode, using +// crossOrigin = "use-credentials". +videoTest("cross-origin + undefined", + cross_origin, '', undefined); +videoTest("cross-origin + anonymous", + cross_origin, 'anonymous', undefined); +videoTest("cross-origin + use-credentials", + cross_origin, 'use-credentials', cookie_cross_origin); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js.headers new file mode 100644 index 0000000000..68fde79c91 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/video.https.window.js.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy:credentialless diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js new file mode 100644 index 0000000000..9190303206 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js @@ -0,0 +1,74 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./credentialless/resources/common.js +// META: script=./resources/common.js + +const cors_coep_headers = coep_require_corp + corp_cross_origin; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +const newIframe = async ( + test, + parent_origin, + parent_headers, + child_origin, + child_headers +) => { + const [future_child, future_error] = + await createIsolatedFrame(parent_origin, parent_headers); + future_error.then(test.unreached_func('cannot create isolated iframe.')); + + const child = await future_child; + add_completion_callback(() => child.remove()); + + const grand_child_token = token(); + const grand_child = child.contentDocument.createElement('iframe'); + grand_child.src = child_origin + executor_path + child_headers + + `&uuid=${grand_child_token}`; + child.contentDocument.body.appendChild(grand_child); + add_completion_callback(() => grand_child.remove()); + + return grand_child_token; +}; + +const childFrameIsCrossOriginIsolated = async ( + test, + child_origin, + parent_permission_coi +) => { + let parent_headers = cors_coep_headers; + const child_headers = cors_coep_headers; + if (parent_permission_coi !== undefined) { + // Escape right parenthesis in WPT pipe: + parent_permission_coi = parent_permission_coi.replace(')', '\\)'); + parent_headers += `|header(permissions-policy,` + + `cross-origin-isolated=${parent_permission_coi})`; + } + const parent_origin = same_origin; + const iframe = await newIframe( + test, + parent_origin, + parent_headers, + child_origin, + child_headers); + return IsCrossOriginIsolated(iframe); +} + +const generate_iframe_test = async (origin, isolation, expect_coi) => { + promise_test_parallel(async (test) => { + const isCrossOriginIsolated = + await childFrameIsCrossOriginIsolated(test, origin, isolation); + assert_equals(isCrossOriginIsolated, expect_coi) + }, `iframe (origin: ${origin}) cross origin isolated (${isolation}) ` + + `permission test`); +} + +generate_iframe_test(same_origin, undefined, true); +generate_iframe_test(same_origin, '*', true); +generate_iframe_test(same_origin, 'self', true); +generate_iframe_test(same_origin, '()', false); +generate_iframe_test(cross_origin, undefined, false); +generate_iframe_test(cross_origin, '*', false); +generate_iframe_test(cross_origin, 'self', false); +generate_iframe_test(cross_origin, '()', false); \ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js.headers new file mode 100644 index 0000000000..3b7825def9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.js.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Opener-Policy: same-origin \ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js new file mode 100644 index 0000000000..d9431cdb50 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js @@ -0,0 +1,170 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=./credentialless/resources/common.js +// META: script=./resources/common.js + +const cors_coep_headers = coep_require_corp + corp_cross_origin; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const dedicatedWorkerPostMessage = ` + self.addEventListener('message', (e) => { + e.data.port.postMessage(self.crossOriginIsolated); + }); +`; + +const postMessageIsWorkerCrossOriginIsolated = async ( + test, + frame, + worker_url +) => { + const worker = new frame.contentWindow.Worker(worker_url); + const mc = new MessageChannel(); + worker.postMessage({port: mc.port2}, [mc.port2]); + worker.onerror = test.unreached_func('cannot create dedicated worker'); + return (await new Promise(r => mc.port1.onmessage = r)).data; +} + +const isDataDedicatedWorkerCrossOriginIsolated = async ( + test, + parent_headers +) => { + const [future_child, future_error] = + await createIsolatedFrame('', parent_headers); + future_error.then(test.unreached_func('cannot create isolated iframe')); + + const child = await future_child; + add_completion_callback(() => child.remove()); + + const worker_url = + `data:application/javascript;base64,${btoa(dedicatedWorkerPostMessage)}`; + return postMessageIsWorkerCrossOriginIsolated(test, child, worker_url); +} + +const isBlobURLDedicatedWorkerCrossOriginIsolated = async( + test, + parent_headers +) => { + const [future_child, future_error] = + await createIsolatedFrame("", parent_headers); + future_error.then(test.unreached_func('cannot create isolated iframe')); + + const child = await future_child; + add_completion_callback(() => child.remove()); + + const blob = + new Blob([dedicatedWorkerPostMessage], {type: 'text/plaintext'}); + const workerURL = URL.createObjectURL(blob); + return postMessageIsWorkerCrossOriginIsolated(test, child, workerURL) +} + +const isHTTPSDedicatedWorkerCrossOriginIsolated = async( + test, + parent_headers +) => { + const [future_child, future_error] = + await createIsolatedFrame("", parent_headers); + future_error.then(test.unreached_func('cannot create isolated iframe')); + + const child = await future_child; + add_completion_callback(() => child.remove()); + + const worker_token = token(); + const workerURL = + `${executor_worker_path}${cors_coep_headers}&uuid=${worker_token}`; + const worker = new child.contentWindow.Worker(workerURL); + return IsCrossOriginIsolated(worker_token); +} + +const sharedWorkerIsCrossOriginIsolated = async( + test, + withCoopCoep +) => { + const [worker, future_error] = + environments.shared_worker(withCoopCoep ? cors_coep_headers : ""); + future_error.then(test.unreached_func('cannot create shared worker.')); + return IsCrossOriginIsolated(worker); +} + +const serviceWorkerIsCrossOriginIsolated = async( + test, + withCoopCoep +) => { + const [worker, future_error] = + environments.service_worker(withCoopCoep ? cors_coep_headers : ""); + future_error.then(test.unreached_func('cannot create service worker.')); + return IsCrossOriginIsolated(worker); +} + +const dedicatedWorkerIsCrossOriginIsolated = async ( + test, + scheme, + parent_permission_coi +) => { + let parent_headers = cors_coep_headers; + if (parent_permission_coi !== undefined) { + // Escape right parenthesis in WPT cors_coep_headers: + parent_permission_coi = parent_permission_coi.replace(')', '\\)'); + parent_headers += `|header(permissions-policy,` + + `cross-origin-isolated=${parent_permission_coi})`; + } + switch (scheme) { + case 'https': + return isHTTPSDedicatedWorkerCrossOriginIsolated(test, parent_headers); + case 'data': + return isDataDedicatedWorkerCrossOriginIsolated(test, parent_headers); + case 'blob': + return isBlobURLDedicatedWorkerCrossOriginIsolated(test, parent_headers); + default: + assert_unreached("wrong scheme for dedicated worker test."); + } +} + +const generate_shared_worker_test = async (withCoopCoep, expected) => { + promise_test_parallel(async (test) => { + const isCrossOriginIsolated = + await sharedWorkerIsCrossOriginIsolated(test, withCoopCoep); + assert_equals(isCrossOriginIsolated, expected) + }, `shared_worker (withCoopCoep: ${withCoopCoep}) ` + + `cross origin isolated permission test`); +} + +const generate_dedicated_worker_test = async ( + scheme, + parent_permission_coi, + expected +) => { + promise_test_parallel(async (test) => { + const isCrossOriginIsolated = + await dedicatedWorkerIsCrossOriginIsolated(test, scheme, parent_permission_coi); + assert_equals(isCrossOriginIsolated, expected) + }, `dedicated_worker (scheme: ${scheme}) cross origin ` + + `isolated (${parent_permission_coi}) permission test`); +} + +const generate_service_worker_test = async (withCoopCoep, expected) => { + promise_test_parallel(async (test) => { + const isCrossOriginIsolated = + await serviceWorkerIsCrossOriginIsolated(test, withCoopCoep); + assert_equals(isCrossOriginIsolated, expected) + }, `service_worker (withCoopCoep: ${withCoopCoep}) ` + + `cross origin isolated permission test`); +} + +generate_shared_worker_test(false, false); +generate_shared_worker_test(true, true); + +generate_dedicated_worker_test('https', undefined, true); +generate_dedicated_worker_test('https', '*', true); +generate_dedicated_worker_test('https', 'self', true); +generate_dedicated_worker_test('https', '()', false); +generate_dedicated_worker_test('data', undefined, false); +generate_dedicated_worker_test('data', '*', false); +generate_dedicated_worker_test('data', 'self', false); +generate_dedicated_worker_test('blob', undefined, true); +generate_dedicated_worker_test('blob', '*', true); +generate_dedicated_worker_test('blob', 'self', true); +generate_dedicated_worker_test('blob', '()', false); + +generate_service_worker_test(false, false); +generate_service_worker_test(true, true); \ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js.headers new file mode 100644 index 0000000000..3b7825def9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/cross-origin-isolated-permission-worker.https.window.js.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Opener-Policy: same-origin \ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html new file mode 100644 index 0000000000..f2878dfc54 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html @@ -0,0 +1,20 @@ + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/data.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html new file mode 100644 index 0000000000..2c97e6f875 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html @@ -0,0 +1,128 @@ + + + Check enforcement of COEP in a DedicatedWorker using CacheStorage. + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker.https.html new file mode 100644 index 0000000000..1ba624181c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/dedicated-worker.https.html @@ -0,0 +1,214 @@ + +COEP and dedicated worker + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/header-parsing.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/header-parsing.https.html new file mode 100644 index 0000000000..7a25eed51f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/header-parsing.https.html @@ -0,0 +1,85 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/iframe-history-none-require-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/iframe-history-none-require-corp.https.html new file mode 100644 index 0000000000..0e7ef8108b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/iframe-history-none-require-corp.https.html @@ -0,0 +1,54 @@ + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html new file mode 100644 index 0000000000..60edf00312 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html @@ -0,0 +1,21 @@ + + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/javascript.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/meta-http-equiv.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/meta-http-equiv.https.html new file mode 100644 index 0000000000..d35df3135a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/meta-http-equiv.https.html @@ -0,0 +1,20 @@ + + +Cross-Origin-Embedder-Policy in <meta http-equiv> + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html new file mode 100644 index 0000000000..e6261f8388 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html @@ -0,0 +1,3 @@ + + +Current page diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/current.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/worker.js new file mode 100644 index 0000000000..44103842a4 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/current/worker.js @@ -0,0 +1 @@ +postMessage('current'); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html new file mode 100644 index 0000000000..d8bd1ae2c0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html @@ -0,0 +1,14 @@ + + +Incumbent page + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/incumbent.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/worker.js new file mode 100644 index 0000000000..03f02a8690 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/incumbent/worker.js @@ -0,0 +1 @@ +postMessage('incumbent'); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/worker.js new file mode 100644 index 0000000000..fcc521e313 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/worker.js @@ -0,0 +1 @@ +postMessage('entry'); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html new file mode 100644 index 0000000000..e1f16a61e1 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html @@ -0,0 +1,49 @@ + + +Multiple globals for Worker constructor: COEP reports + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html new file mode 100644 index 0000000000..6e1573cd64 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html @@ -0,0 +1,19 @@ + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/no-secure-context.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html new file mode 100644 index 0000000000..7fed1fe581 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html @@ -0,0 +1,21 @@ + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none-load-from-cache-storage.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-load-from-cache-storage.https.html new file mode 100644 index 0000000000..177ae8d11b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-load-from-cache-storage.https.html @@ -0,0 +1,173 @@ + + + Retrieve resources from CacheStorage with Cross-Origin-Embedder-Policy: require-corp + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-none.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-none.https.html new file mode 100644 index 0000000000..b539561eff --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-none.https.html @@ -0,0 +1,89 @@ + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html new file mode 100644 index 0000000000..36cf4a153b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html @@ -0,0 +1,93 @@ + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none-sw-from-require-corp.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html new file mode 100644 index 0000000000..cf9b34b4ca --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html @@ -0,0 +1,91 @@ + +Cross-Origin-Embedder-Policy header and nested navigable resource without such header + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html.headers new file mode 100644 index 0000000000..43c44cffd6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/none.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: unknown-should-be-parsed-as-null diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js new file mode 100644 index 0000000000..f4d59955af --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js @@ -0,0 +1,2 @@ +// META: global=window,worker,sharedworker-module,serviceworker-module +test(t => assert_equals(crossOriginEmbedderPolicy, "credentialless")); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js.headers new file mode 100644 index 0000000000..32523a6978 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-credentialless.tentative.https.any.js.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: credentialless diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js new file mode 100644 index 0000000000..f6019c2457 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js @@ -0,0 +1,2 @@ +// META: global=window,worker,sharedworker-module,serviceworker-module +test(t => assert_equals(crossOriginEmbedderPolicy, "require-corp")); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-require-corp.tentative.https.any.js.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.js new file mode 100644 index 0000000000..d2890901eb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reflection-unsafe-none.tentative.https.any.js @@ -0,0 +1,2 @@ +// META: global=window,worker,sharedworker-module,serviceworker-module +test(t => assert_equals(crossOriginEmbedderPolicy, "unsafe-none")); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html new file mode 100644 index 0000000000..ff9e5b64a0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html @@ -0,0 +1,86 @@ + + +Cross-Origin-Embedder-Policy-Report-Only header does not affect the actual behavior + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html.headers new file mode 100644 index 0000000000..289659a41f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/report-only-require-corp.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy-report-only: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-navigation.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-navigation.https.html new file mode 100644 index 0000000000..dea8947818 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-navigation.https.html @@ -0,0 +1,170 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html new file mode 100644 index 0000000000..e56124a4a0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html @@ -0,0 +1,206 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-document-reporting-endpoint.https.window.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-document-reporting-endpoint.https.window.js new file mode 100644 index 0000000000..09800db2b8 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-document-reporting-endpoint.https.window.js @@ -0,0 +1,140 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js + +// This file consists of tests for COEP reporting using Reporting-Endpoints +// header. It exclusively tests that reports can be sent to Reporting-Endpoint +// configured endpoint. +const { REMOTE_ORIGIN } = get_host_info(); + +const REPORT_ENDPOINT = token(); +const REPORT_ONLY_ENDPOINT = token(); +const FRAME_URL = `resources/reporting-empty-frame.html` + + `?pipe=header(cross-origin-embedder-policy,require-corp;report-to="endpoint")` + + `|header(cross-origin-embedder-policy-report-only,require-corp;report-to="report-only-endpoint")` + + `|header(reporting-endpoints, endpoint="/html/cross-origin-embedder-policy/resources/report.py?key=${REPORT_ENDPOINT}"\\, report-only-endpoint="/html/cross-origin-embedder-policy/resources/report.py?key=${REPORT_ONLY_ENDPOINT}")`; + +function wait(ms) { + return new Promise(resolve => step_timeout(resolve, ms)); +} + +async function fetchReports(endpoint) { + const res = await fetch(`resources/report.py?key=${endpoint}`, { + cache: 'no-store' + }); + if (res.status == 200) { + return await res.json(); + } + return []; +} + +async function fetchCoepReport( + endpoint, type, blockedUrl, contextUrl, disposition) { + blockedUrl = new URL(blockedUrl, location).href; + contextUrl = new URL(contextUrl, location).href; + const reports = await fetchReports(endpoint); + return reports.find(r => ( + r.type == 'coep' && + r.url == contextUrl && + r.body.type == type && + r.body.blockedURL === blockedUrl && + r.body.disposition === disposition)); +} + +async function checkCorpReportExists( + endpoint, blockedUrl, contextUrl, destination, disposition) { + blockedUrl = new URL(blockedUrl, location).href; + contextUrl = new URL(contextUrl, location).href; + contextUrl.replace(REPORT_ENDPOINT, "REPORT_ENDPOINT_UUID"); + contextUrl.replace(REPORT_ONLY_ENDPOINT, "REPORT_ONLY_ENDPOINT_UUID"); + const report = await fetchCoepReport( + endpoint, 'corp', blockedUrl, contextUrl, disposition); + assert_true(!!report, + `A corp report with blockedURL ${blockedUrl.split("?")[0]} ` + + `and url ${contextUrl} is not found.`); + assert_equals(report.body.destination, destination); +} + +async function checkNavigationReportExists( + endpoint, blockedUrl, contextUrl, disposition) { + blockedUrl = new URL(blockedUrl, location).href; + contextUrl = new URL(contextUrl, location).href; + contextUrl.replace(REPORT_ENDPOINT, "REPORT_ENDPOINT_UUID"); + contextUrl.replace(REPORT_ONLY_ENDPOINT, "REPORT_ONLY_ENDPOINT_UUID"); + const report = await fetchCoepReport( + endpoint, 'navigation', blockedUrl, contextUrl, disposition); + assert_true(!!report, + `A navigation report with blockedURL ${blockedUrl.split("?")[0]} ` + + `and url ${contextUrl} is not found.`); +} + +promise_test(async t => { + const iframe = document.createElement('iframe'); + t.add_cleanup(() => iframe.remove()); + + iframe.src = FRAME_URL; + await new Promise(resolve => { + iframe.addEventListener('load', resolve, { once: true }); + document.body.appendChild(iframe); + }); + + const url = `${REMOTE_ORIGIN}/common/text-plain.txt?${token()}`; + const init = { mode: 'no-cors', cache: 'no-store' }; + // The response comes from cross-origin, and doesn't have a CORP + // header, so it is blocked. + iframe.contentWindow.fetch(url, init).catch(() => { }); + + // Wait for reports to be uploaded. + await wait(1000); + await checkCorpReportExists( + REPORT_ENDPOINT, url, iframe.src, '', 'enforce'); + await checkCorpReportExists( + REPORT_ONLY_ENDPOINT, url, iframe.src, '', 'reporting'); +}, 'subresource CORP'); + +promise_test(async t => { + const iframe = document.createElement('iframe'); + t.add_cleanup(() => iframe.remove()); + + iframe.src = FRAME_URL; + await new Promise(resolve => { + iframe.addEventListener('load', resolve, { once: true }); + document.body.appendChild(iframe); + }); + + const url = `${REMOTE_ORIGIN}/common/blank.html?${token()}`; + // The nested frame comes from cross-origin and doesn't have a CORP + // header, so it is blocked. + const nested = iframe.contentWindow.document.createElement('iframe'); + nested.src = url; + iframe.contentWindow.document.body.appendChild(nested); + + // Wait for reports to be uploaded. + await wait(1000); + await checkCorpReportExists( + REPORT_ENDPOINT, url, iframe.src, 'iframe', 'enforce'); + await checkCorpReportExists( + REPORT_ONLY_ENDPOINT, url, iframe.src, 'iframe', 'reporting'); +}, 'navigation CORP on cross origin'); + +promise_test(async (t) => { + const iframe = document.createElement('iframe'); + t.add_cleanup(() => iframe.remove()); + + iframe.src = FRAME_URL; + const targetUrl = `/common/blank.html?${token()}`; + iframe.addEventListener('load', t.step_func(() => { + const nested = iframe.contentDocument.createElement('iframe'); + nested.src = targetUrl; + // |nested| doesn't have COEP whereas |iframe| has, so it is blocked. + iframe.contentDocument.body.appendChild(nested); + }), { once: true }); + + document.body.appendChild(iframe); + + // Wait for reports to be uploaded. + await wait(1000); + await checkNavigationReportExists( + REPORT_ENDPOINT, targetUrl, iframe.src, 'enforce'); + await checkNavigationReportExists( + REPORT_ONLY_ENDPOINT, targetUrl, iframe.src, 'reporting'); +}, 'navigation CORP on same origin'); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html new file mode 100644 index 0000000000..39c3de7076 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html @@ -0,0 +1,209 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html.sub.headers new file mode 100644 index 0000000000..fe2f651dae --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html.sub.headers @@ -0,0 +1 @@ +Reporting-Endpoints: endpoint="https://{{host}}:{{ports[https][0]}}//html/cross-origin-embedder-policy/resources/report.py?key=4d8b6d86-c9a8-47c1-871b-111169a8f79c", report-only-endpoint="/html/cross-origin-embedder-policy/resources/report.py?key=5d7c1e33-ef88-43c2-9ca3-c67ff300b8c2" diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-frame-owner.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-frame-owner.https.html new file mode 100644 index 0000000000..331ad898eb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-frame-owner.https.html @@ -0,0 +1,87 @@ + + + +Check COEP reports are sent to iframe for 'new Worker()' failure + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-worker-owner.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-worker-owner.https.html new file mode 100644 index 0000000000..c0010876fa --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/reporting-to-worker-owner.https.html @@ -0,0 +1,89 @@ + + + +Check COEP reports are sent to parent worker for 'new Worker()' failure + + + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html new file mode 100644 index 0000000000..945333b83d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html @@ -0,0 +1,48 @@ + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html new file mode 100644 index 0000000000..5d06286d91 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html @@ -0,0 +1,48 @@ + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html new file mode 100644 index 0000000000..269698bc1a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html @@ -0,0 +1,74 @@ + + + Images on a page Cross-Origin-Embedder-Policy: require-corp should load the same from the cache or network + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-cached-images.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html new file mode 100644 index 0000000000..489230a776 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html @@ -0,0 +1,179 @@ + + + Retrieve resources from CacheStorage with Cross-Origin-Embedder-Policy: require-corp + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-revalidated-images.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-revalidated-images.https.html new file mode 100644 index 0000000000..420190aad3 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-revalidated-images.https.html @@ -0,0 +1,76 @@ + + + Images on a page Cross-Origin-Embedder-Policy: require-corp should load the same from the cache or network, even with revalidation + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-none.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-none.https.html new file mode 100644 index 0000000000..a60b8bd457 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-none.https.html @@ -0,0 +1,92 @@ + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html new file mode 100644 index 0000000000..deefc92b80 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html @@ -0,0 +1,93 @@ + + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw-from-require-corp.https.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw.https.html new file mode 100644 index 0000000000..05272d41a4 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-sw.https.html @@ -0,0 +1,53 @@ + +Cross Origin Embedder Policy: requests initiated from a service worker with 'require-corp' + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-worker-script-revalidation.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-worker-script-revalidation.html new file mode 100644 index 0000000000..74794967fb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp-worker-script-revalidation.html @@ -0,0 +1,25 @@ + +COEP and dedicated worker + + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html new file mode 100644 index 0000000000..d187e0f760 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html @@ -0,0 +1,251 @@ + + +Cross-Origin-Embedder-Policy header and nested navigable resource without such header + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/require-corp.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html new file mode 100644 index 0000000000..928d404672 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html @@ -0,0 +1,24 @@ + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers new file mode 100644 index 0000000000..4e798cd9f5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: cross-origin diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/cache-storage-reporting.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/cache-storage-reporting.js new file mode 100644 index 0000000000..86dff9c845 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/cache-storage-reporting.js @@ -0,0 +1,63 @@ +function remote(path) { + const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN; + return new URL(path, REMOTE_ORIGIN).href; +} + +function local(path) { + return new URL(path, location.origin).href; +} + +function encode(url) { + return encodeURI(url).replace(/\;/g, '%3B'); +} + +const resource_path = (new URL('./resources', location)).pathname; +const header_coep = '|header(Cross-Origin-Embedder-Policy,require-corp)'; +const header_coep_report_only = + '|header(Cross-Origin-Embedder-Policy-Report-Only,require-corp)'; + +const iframe_path = resource_path + '/iframe.html?pipe='; +const worker_path = resource_path + '/reporting-worker.js?pipe='; +const image_url = remote('/images/blue.png'); + +// This script attempt to load a COEP:require-corp CORP:undefined response from +// the CacheStorage. +// +// Executed from different context: +// - A Document +// - A ServiceWorker +// - A DedicatedWorker +// - A SharedWorker +// +// The context has either COEP or COEP-Report-Only defined. +const eval_script = ` + (async function() { + try { + const cache = await caches.open('v1'); + const request = new Request('${image_url}', { mode: 'no-cors' }); + const response = await cache.match(request); + } catch(e) { + } + })() +`; + +promise_setup(async (t) => { + const cache = await caches.open('v1'); + const request = new Request(image_url, {mode: 'no-cors'}); + const response = await fetch(request); + await cache.put(request, response); +}, 'Setup: store a CORS:cross-origin COEP:none response into CacheStorage') + +async function makeIframe(test, iframe_url) { + const iframe = document.createElement('iframe'); + test.add_cleanup(() => iframe.remove()); + iframe.src = iframe_url; + const iframe_loaded = new Promise(resolve => iframe.onload = resolve); + document.body.appendChild(iframe); + await iframe_loaded; + return iframe; +} + +function wait(ms) { + return new Promise(resolve => step_timeout(resolve, ms)); +} diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html new file mode 100644 index 0000000000..78c1331132 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html @@ -0,0 +1,2 @@ + +

Cross-Origin-Embedder-Policy: require-corp header set. diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/coep-frame.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/common.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/common.js new file mode 100644 index 0000000000..8f038a7278 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/common.js @@ -0,0 +1,19 @@ +async function createIsolatedFrame(origin, headers) { + const parent = document.createElement('iframe'); + const parent_loaded = new Promise(r => parent.onload = () => { r(parent); }); + const error = new Promise(r => parent.onerror = r); + parent.src = origin + "/common/blank.html?pipe=" + headers; + parent.anonymous = false; + document.body.appendChild(parent); + return [parent_loaded, error]; +} + +async function IsCrossOriginIsolated(from_token) { + const reply_token = token(); + send(from_token, ` + send("${reply_token}", self.crossOriginIsolated); + `); + const reply = await receive(reply_token); + assert_true(reply.match(/true|false/) != null); + return reply == 'true'; +} \ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/corp-image.py b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/corp-image.py new file mode 100644 index 0000000000..e507846181 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/corp-image.py @@ -0,0 +1,31 @@ +import json +import base64 + +# A 1x1 PNG image. +# Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain) +IMAGE = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=" + +def main(request, response): + response.headers.set(b'Access-Control-Allow-Origin', b'*') + response.headers.set(b'Access-Control-Allow-Methods', b'OPTIONS, GET, POST') + response.headers.set(b'Access-Control-Allow-Headers', b'Content-Type') + + # CORS preflight + if request.method == u'OPTIONS': + return u'' + + if b'true' == request.GET.get(b'revalidate', None): + response.headers.set(b'Cache-Control', b'max-age=0, must-revalidate') + else: + response.headers.set(b'Cache-Control', b'max-age=3600'); + + if b'some-etag' == request.headers.get(b'If-None-Match', None): + response.status = 304 + return u'' + + if request.GET.get(b'corp-cross-origin', None): + response.headers.set(b'Cross-Origin-Resource-Policy', b'cross-origin') + + response.headers.set(b'Etag', b'some-etag') + response.headers.set(b'Content-Type', b'image/png') + return base64.b64decode(IMAGE) diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker-supporting-revalidation.py b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker-supporting-revalidation.py new file mode 100755 index 0000000000..eef86d1c55 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker-supporting-revalidation.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + + +def main(request, response): + headers = [] + if request.headers.get(b'if-none-match', None): + status = 304, u"Not Modified" + return status, headers, u"" + else: + headers.append((b"Content-Type", b"text/javascript")) + headers.append((b"Cross-Origin-Embedder-Policy", b"require-corp")) + headers.append((b"Cache-Control", b"private, max-age=0, must-revalidate")) + headers.append((b"ETag", b"abcdef")) + status = 200, u"OK" + return status, headers, u"self.onmessage = (e) => { self.postMessage('LOADED'); };" diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js new file mode 100644 index 0000000000..66f3cc3d41 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js @@ -0,0 +1,7 @@ +self.onmessage = (e) => { + fetch(e.data, {mode: 'no-cors'}).then(() => { + self.postMessage('LOADED'); + }, () => { + self.postMessage('FAILED'); + }); +}; diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/empty-coep.py b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/empty-coep.py new file mode 100644 index 0000000000..d0e547b130 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/empty-coep.py @@ -0,0 +1,7 @@ +def main(request, response): + headers = [(b'Content-Type', b'text/html')] + + for value in request.GET.get_list(b'value'): + headers.append((b'Cross-Origin-Embedder-Policy', value)) + + return (200, headers, u'') diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html new file mode 100644 index 0000000000..6b0f96221d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html @@ -0,0 +1,91 @@ + + +Fetch and create Blob + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-in-dedicated-worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-in-dedicated-worker.js new file mode 100644 index 0000000000..bd60d07952 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/fetch-in-dedicated-worker.js @@ -0,0 +1,6 @@ +self.addEventListener('message', async (e) => { + const param = e.data; + // Ignore network error. + await fetch(param.url, param.init).catch(() => {}); + self.postMessage(param.url); +}); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/iframe.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/iframe.html new file mode 100644 index 0000000000..a6b74ad924 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/iframe.html @@ -0,0 +1,3 @@ + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html new file mode 100644 index 0000000000..288610046e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html @@ -0,0 +1,38 @@ + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html.headers new file mode 100644 index 0000000000..8df98474b5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/load-corp-images.html.headers @@ -0,0 +1 @@ +cross-origin-embedder-policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html new file mode 100644 index 0000000000..f1437ba90a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html @@ -0,0 +1,34 @@ + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html new file mode 100644 index 0000000000..910317d29b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html @@ -0,0 +1,29 @@ + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html.headers new file mode 100644 index 0000000000..56d0ac3428 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp-same-site.sub.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: same-site diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html new file mode 100644 index 0000000000..0a3c4dd8d7 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html @@ -0,0 +1,24 @@ + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt new file mode 100644 index 0000000000..e61d8ee36c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt @@ -0,0 +1 @@ +nothing with cross-origin CORP diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers new file mode 100644 index 0000000000..1b88136c01 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers @@ -0,0 +1 @@ +Cross-Origin-Resource-Policy: cross-origin diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt new file mode 100644 index 0000000000..b9ba801f78 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt @@ -0,0 +1 @@ +nothing with same-origin CORP diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers new file mode 100644 index 0000000000..30ddeac2e7 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers @@ -0,0 +1 @@ +Cross-Origin-Resource-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/postmessage-ready.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/postmessage-ready.html new file mode 100644 index 0000000000..3282711dbc --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/postmessage-ready.html @@ -0,0 +1,4 @@ + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/report.py b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/report.py new file mode 100644 index 0000000000..100c642d6c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/report.py @@ -0,0 +1,41 @@ +import json + +def main(request, response): + response.headers.set(b'Access-Control-Allow-Origin', b'*') + response.headers.set(b'Access-Control-Allow-Methods', b'OPTIONS, GET, POST') + response.headers.set(b'Access-Control-Allow-Headers', b'Content-Type') + response.headers.set(b'Cache-Control', b'no-cache, no-store, must-revalidate') + + # CORS preflight + if request.method == u'OPTIONS': + return u'' + + uuidMap = { + b'endpoint': b'01234567-0123-0123-0123-0123456789AB', + b'report-only-endpoint': b'01234567-0123-0123-0123-0123456789CD' + } + key = 0 + if b'endpoint' in request.GET: + key = uuidMap.get(request.GET[b'endpoint'], 0) + + if b'key' in request.GET: + key = request.GET[b'key'] + + if key == 0: + response.status = 400 + return u'invalid endpoint' + + path = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + if request.method == u'POST': + reports = request.server.stash.take(key, path) or [] + for report in json.loads(request.body): + reports.append(report) + request.server.stash.put(key, reports, path) + return u'done' + + if request.method == u'GET': + response.headers.set(b'Content-Type', b'application/json') + return json.dumps(request.server.stash.take(key, path) or []) + + response.status = 400 + return u'invalid method' diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame-multiple-headers.html.asis b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame-multiple-headers.html.asis new file mode 100644 index 0000000000..c0b352f1c7 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame-multiple-headers.html.asis @@ -0,0 +1,9 @@ +HTTP/1.1 200 OK +Content-Type: text/html +cross-origin-embedder-policy: require-corp; foo=" +cross-origin-embedder-policy: "; report-to="endpoint" +cross-origin-embedder-policy-report-only: require-corp; foo=" +cross-origin-embedder-policy-report-only: "; report-to="report-only-endpoint" + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html new file mode 100644 index 0000000000..b1579add2e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html @@ -0,0 +1,5 @@ + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-worker.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-worker.js new file mode 100644 index 0000000000..0f8a2ce4c8 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/reporting-worker.js @@ -0,0 +1,25 @@ +function run({script, port}) { + const reports = []; + const observer = new ReportingObserver((rs) => { + for (const r of rs) { + reports.push(r.toJSON()); + } + }); + // Wait 200ms for reports to settle. + setTimeout(() => { + observer.disconnect(); + port.postMessage(reports); + }, 200); + observer.observe(); + + // This eval call may generate some reports. + eval(script); +} + +// For DedicatedWorker and ServiceWorker +self.addEventListener('message', (e) => run(e.data)); + +// For SharedWorker +self.addEventListener('connect', (e) => { + e.ports[0].onmessage = (ev) => run(ev.data); +}); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js new file mode 100644 index 0000000000..e652c5bf30 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js @@ -0,0 +1,23 @@ +// Service worker with 'COEP: require-corp' response header. +// This service worker issues a network request to import scripts with or +// without CORP response header. + +importScripts("/common/get-host-info.sub.js"); + +function url_for_empty_js(corp) { + const url = new URL(get_host_info().HTTPS_REMOTE_ORIGIN); + url.pathname = '/service-workers/service-worker/resources/empty.js'; + if (corp) { + url.searchParams.set( + 'pipe', `header(Cross-Origin-Resource-Policy, ${corp})`); + } + return url.href; +} + +const params = new URL(location.href).searchParams; + +if (params.get('corp') === 'cross-origin') { + importScripts(url_for_empty_js('cross-origin')); +} else { + importScripts(url_for_empty_js()); +} diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw-import-scripts.js.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js new file mode 100644 index 0000000000..10f05726fa --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js @@ -0,0 +1,27 @@ +// Service worker with 'COEP: require-corp' response header. +// This service worker issues a network request for a resource with or without +// CORP response header. + +importScripts("/common/get-host-info.sub.js"); + +self.addEventListener('message', e => { + e.waitUntil((async () => { + let result; + try { + let url; + if (e.data === 'WithCorp') { + url = get_host_info().HTTPS_REMOTE_ORIGIN + + '/html/cross-origin-embedder-policy/resources/' + + 'nothing-cross-origin-corp.txt'; + } else if (e.data === 'WithoutCorp') { + url = get_host_info().HTTPS_REMOTE_ORIGIN + '/common/blank.html'; + } + const response = await fetch(url, { mode: 'no-cors' }); + result = response.type; + } catch (error) { + result = `Exception: ${error.name}`; + } finally { + e.source.postMessage(result); + } + })()); +}); diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/require-corp-sw.js.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/script-factory.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/script-factory.js new file mode 100644 index 0000000000..ac7a1fda06 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/script-factory.js @@ -0,0 +1,30 @@ +// This creates a serialized diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-owner.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-owner.js new file mode 100644 index 0000000000..d1f172a0b8 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-owner.js @@ -0,0 +1,36 @@ +const is_worker = !('window' in self); +const parent_or_self = is_worker ? self : self.parent; + +function startWorkerAndObserveReports(worker_url, wait_for_report) { + const worker = new Worker(worker_url); + const result_promise = new Promise(resolve => { + worker.onmessage = _ => resolve('success'); + worker.onerror = _ => resolve('error'); + }); + worker.postMessage("postMessage('reply to owner from worker');"); + + const report_promise = new Promise(resolve => { + const observer = new ReportingObserver(reports => { + observer.disconnect(); + resolve(reports.map(r => r.toJSON())); + }); + observer.observe(); + }); + + if (wait_for_report) { + Promise.all([result_promise, report_promise]).then(results => { + parent_or_self.postMessage(results[1]); + }); + } else { + result_promise.then(result => { + parent_or_self.postMessage([]); + }); + } +} + +if (is_worker) { + onmessage = e => { + startWorkerAndObserveReports(e.data.worker_url, e.data.wait_for_report); + }; +} + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-support.js b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-support.js new file mode 100644 index 0000000000..860ee6826c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/resources/worker-support.js @@ -0,0 +1,81 @@ +// Configures `url` such that the response carries a `COEP: ${value}` header. +// +// `url` must be a `URL` instance. +function setCoep(url, value) { + url.searchParams + .set("pipe", `header(cross-origin-embedder-policy,${value})`); +} + +// Resolves the given `relativeUrl` relative to the current window's location. +// +// `options` can contain the following keys: +// +// - `coep`: value passed to `setCoep()`, if present. +// - `host`: overrides the host of the returned URL. +// +// Returns a `URL` instance. +function resolveUrl(relativeUrl, options) { + const url = new URL(relativeUrl, window.location); + + if (options !== undefined) { + const { coep, host } = options; + if (coep !== undefined) { + setCoep(url, coep); + } + if (host !== undefined) { + url.host = host; + } + } + + return url; +} + +// Adds an iframe loaded from `url` to the current document, waiting for it to +// load before returning. +// +// The returned iframe is removed from the document at the end of the test `t`. +async function withIframe(t, url) { + const frame = document.createElement("iframe"); + frame.src = url; + + t.add_cleanup(() => frame.remove()); + + const loadedPromise = new Promise(resolve => { + frame.addEventListener('load', resolve, {once: true}); + }); + document.body.append(frame); + await loadedPromise; + + return frame; +} + +// Asynchronously waits for a single "message" event on the given `target`. +function waitForMessage(target) { + return new Promise(resolve => { + target.addEventListener('message', resolve, {once: true}); + }); +} + +// Fetches `url` from a document with COEP `creatorCoep`, then serializes it +// and returns a URL pointing to the fetched body with the given `scheme`. +// +// - `creatorCoep` is passed to `setCoep()`. +// - `scheme` may be one of: "blob", "data" or "filesystem". +// +// The returned URL is valid until the end of the test `t`. +async function createLocalUrl(t, { url, creatorCoep, scheme }) { + const frameUrl = resolveUrl("resources/fetch-and-create-url.html", { + coep: creatorCoep, + }); + frameUrl.searchParams.set("url", url); + frameUrl.searchParams.set("scheme", scheme); + + const messagePromise = waitForMessage(window); + const frame = await withIframe(t, frameUrl); + + const evt = await messagePromise; + const message = evt.data; + assert_equals(message.error, undefined, "url creation error"); + + return message.url; +} diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html new file mode 100644 index 0000000000..1e3f80a918 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html @@ -0,0 +1,40 @@ + + + + + +

+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/sandbox.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html new file mode 100644 index 0000000000..873f06ce4f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html @@ -0,0 +1,117 @@ + + + Check enforcement of COEP in a ServiceWorker using CacheStorage. + + + + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/shared-workers.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/shared-workers.https.html new file mode 100644 index 0000000000..2558f2dd0b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/shared-workers.https.html @@ -0,0 +1,228 @@ + + + +COEP - policy derivation for Shared Workers + + + + + +

Verify the Cross-Origin Embedder Policy for Shared Workers by performing a +cross-domain "fetch" request for a resource that does not specify a COEP. Only +Shared Workers with the default COEP should be able to successfully perform +this operation.

+ + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html new file mode 100644 index 0000000000..2937c13381 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html @@ -0,0 +1,21 @@ + + + + + + +
+ diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html new file mode 100644 index 0000000000..e96c7f7e5d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html @@ -0,0 +1,61 @@ + +Test that local scheme workers inherit COEP: require-corp from the creating document + + + diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html.headers b/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/worker-inheritance.sub.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp -- cgit v1.2.3