From adead3af527a2a452175a63409c7d32e1e4419d6 Mon Sep 17 00:00:00 2001 From: Sam LeDoux Date: Tue, 3 Dec 2024 12:30:54 -0800 Subject: [PATCH] Add Initial Web Platform Tests for Storage Access Headers This change adds web platform tests that confirm the inclusion of the `Sec-Fetch-Storage-Access` header on cross-site navigations, and that confirm the browser properly handles responses which include the `Activate-Storage-Access` header. Bug: 332335089 Change-Id: If453daea7b77292a6498f22b86a552a5a064b521 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5972601 Reviewed-by: Avi Drissman Reviewed-by: Chris Fredrickson Commit-Queue: Sam LeDoux Cr-Commit-Position: refs/heads/main@{#1391183} --- .../generated/audioworklet.https.sub.html | 26 + .../css-font-face.https.sub.tentative.html | 20 + .../css-font-face.sub.tentative.html | 30 ++ .../css-images.https.sub.tentative.html | 145 ++++++ .../generated/css-images.sub.tentative.html | 210 ++++++++ .../generated/element-a.https.sub.html | 40 ++ fetch/metadata/generated/element-a.sub.html | 60 +++ .../generated/element-area.https.sub.html | 40 ++ .../metadata/generated/element-area.sub.html | 60 +++ .../generated/element-audio.https.sub.html | 27 + .../metadata/generated/element-audio.sub.html | 39 ++ .../generated/element-embed.https.sub.html | 21 + .../metadata/generated/element-embed.sub.html | 30 ++ .../generated/element-frame.https.sub.html | 29 ++ .../metadata/generated/element-frame.sub.html | 42 ++ .../generated/element-iframe.https.sub.html | 29 ++ .../generated/element-iframe.sub.html | 42 ++ ...ment-img-environment-change.https.sub.html | 29 ++ .../element-img-environment-change.sub.html | 42 ++ .../generated/element-img.https.sub.html | 58 +++ fetch/metadata/generated/element-img.sub.html | 84 +++ .../element-input-image.https.sub.html | 21 + .../generated/element-input-image.sub.html | 30 ++ .../element-link-icon.https.sub.html | 31 ++ .../generated/element-link-icon.sub.html | 45 ++ ...ment-link-prefetch.https.optional.sub.html | 31 ++ .../element-link-prefetch.optional.sub.html | 45 ++ ...ement-meta-refresh.https.optional.sub.html | 24 + .../element-meta-refresh.optional.sub.html | 36 ++ .../generated/element-picture.https.sub.html | 93 ++++ .../generated/element-picture.sub.html | 135 +++++ .../generated/element-script.https.sub.html | 31 ++ .../generated/element-script.sub.html | 90 ++++ .../element-video-poster.https.sub.html | 21 + .../generated/element-video-poster.sub.html | 30 ++ .../generated/element-video.https.sub.html | 27 + .../metadata/generated/element-video.sub.html | 39 ++ .../fetch-via-serviceworker.https.sub.html | 62 +++ fetch/metadata/generated/fetch.https.sub.html | 27 + fetch/metadata/generated/fetch.sub.html | 39 ++ .../generated/form-submission.https.sub.html | 44 ++ .../generated/form-submission.sub.html | 66 +++ .../generated/header-link.https.sub.html | 58 +++ fetch/metadata/generated/header-link.sub.html | 84 +++ .../header-refresh.https.optional.sub.html | 24 + .../header-refresh.optional.sub.html | 36 ++ ...cript-module-import-dynamic.https.sub.html | 26 + .../script-module-import-dynamic.sub.html | 39 ++ ...script-module-import-static.https.sub.html | 28 + .../script-module-import-static.sub.html | 42 ++ .../generated/svg-image.https.sub.html | 29 ++ fetch/metadata/generated/svg-image.sub.html | 42 ++ .../generated/window-history.https.sub.html | 44 ++ .../generated/window-history.sub.html | 66 +++ .../generated/window-location.https.sub.html | 112 ++++ .../generated/window-location.sub.html | 168 ++++++ .../worker-dedicated-constructor.sub.html | 15 + ...ker-dedicated-importscripts.https.sub.html | 27 + .../worker-dedicated-importscripts.sub.html | 39 ++ fetch/metadata/tools/fetch-metadata.conf.yml | 81 +++ storage-access-api/helpers.js | 11 +- .../resources/handle-headers-non-retry.py | 20 + .../resources/handle-headers-retry.py | 43 ++ .../resources/header-helpers.py | 58 +++ .../nested-handle-storage-access-headers.py | 5 + .../retrieve-storage-access-headers.py | 17 + ...cess-headers.tentative.https.sub.window.js | 487 ++++++++++++++++++ 67 files changed, 3669 insertions(+), 2 deletions(-) create mode 100644 storage-access-api/resources/handle-headers-non-retry.py create mode 100644 storage-access-api/resources/handle-headers-retry.py create mode 100644 storage-access-api/resources/header-helpers.py create mode 100644 storage-access-api/resources/nested-handle-storage-access-headers.py create mode 100644 storage-access-api/resources/retrieve-storage-access-headers.py create mode 100644 storage-access-api/storage-access-headers.tentative.https.sub.window.js diff --git a/fetch/metadata/generated/audioworklet.https.sub.html b/fetch/metadata/generated/audioworklet.https.sub.html index 64fb7607e26a17..5ea1cdc8bc986b 100644 --- a/fetch/metadata/generated/audioworklet.https.sub.html +++ b/fetch/metadata/generated/audioworklet.https.sub.html @@ -266,6 +266,32 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/javascript'}), + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/javascript'}), + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/css-font-face.https.sub.tentative.html b/fetch/metadata/generated/css-font-face.https.sub.tentative.html index 332effeb1f80a5..481355c0a6ca71 100644 --- a/fetch/metadata/generated/css-font-face.https.sub.tentative.html +++ b/fetch/metadata/generated/css-font-face.https.sub.tentative.html @@ -225,6 +225,26 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsCrossSite'])) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsSameSite'])) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/css-font-face.sub.tentative.html b/fetch/metadata/generated/css-font-face.sub.tentative.html index 8a0b90cee103db..a0d2a06fed3e75 100644 --- a/fetch/metadata/generated/css-font-face.sub.tentative.html +++ b/fetch/metadata/generated/css-font-face.sub.tentative.html @@ -160,6 +160,36 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpOrigin'])) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpSameSite'])) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpCrossSite'])) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/css-images.https.sub.tentative.html b/fetch/metadata/generated/css-images.https.sub.tentative.html index 3fa240192894e0..63dcb4bf027a6a 100644 --- a/fetch/metadata/generated/css-images.https.sub.tentative.html +++ b/fetch/metadata/generated/css-images.https.sub.tentative.html @@ -1374,6 +1374,151 @@ .then(t.step_func_done(), t.unreached_func()); }, 'list-style-image sec-fetch-user'); + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite']); + + declarations.push(`background-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_equals(headers['sec-fetch-storage-access'], 'none'); + }) + .then(t.step_func_done(), (error) => t.unreached_func()); + }, 'background-image sec-fetch-storage-access - Cross-site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite']); + + declarations.push(`border-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'border-image sec-fetch-storage-access - Cross-site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite']); + + declarations.push(`content: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'content sec-fetch-storage-access - Cross-site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite']); + + declarations.push(`cursor: url("${url}"), auto;`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'cursor sec-fetch-storage-access - Cross-site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite']); + + declarations.push(`list-style-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'list-style-image sec-fetch-storage-access - Cross-site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite']); + + declarations.push(`background-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), (error) => t.unreached_func()); + }, 'background-image sec-fetch-storage-access - Same site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite']); + + declarations.push(`border-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'border-image sec-fetch-storage-access - Same site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite']); + + declarations.push(`content: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'content sec-fetch-storage-access - Same site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite']); + + declarations.push(`cursor: url("${url}"), auto;`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'cursor sec-fetch-storage-access - Same site'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite']); + + declarations.push(`list-style-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'list-style-image sec-fetch-storage-access - Same site'); + iframe.srcdoc = declarations.map((declaration, index) => `
` ).join(''); diff --git a/fetch/metadata/generated/css-images.sub.tentative.html b/fetch/metadata/generated/css-images.sub.tentative.html index f1ef27cf08730e..2f6f2f75f1b9a0 100644 --- a/fetch/metadata/generated/css-images.sub.tentative.html +++ b/fetch/metadata/generated/css-images.sub.tentative.html @@ -869,6 +869,216 @@ .then(t.step_func_done(), t.unreached_func()); }, 'list-style-image sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin']); + + declarations.push(`background-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), (error) => t.unreached_func()); + }, 'background-image sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin']); + + declarations.push(`border-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'border-image sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin']); + + declarations.push(`content: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'content sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin']); + + declarations.push(`cursor: url("${url}"), auto;`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'cursor sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin']); + + declarations.push(`list-style-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'list-style-image sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite']); + + declarations.push(`background-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), (error) => t.unreached_func()); + }, 'background-image sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite']); + + declarations.push(`border-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'border-image sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite']); + + declarations.push(`content: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'content sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite']); + + declarations.push(`cursor: url("${url}"), auto;`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'cursor sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite']); + + declarations.push(`list-style-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'list-style-image sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite']); + + declarations.push(`background-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), (error) => t.unreached_func()); + }, 'background-image sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite']); + + declarations.push(`border-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'border-image sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite']); + + declarations.push(`content: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'content sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite']); + + declarations.push(`cursor: url("${url}"), auto;`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'cursor sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + + async_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite']); + + declarations.push(`list-style-image: url("${url}");`); + + whenIframeReady + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }) + .then(t.step_func_done(), t.unreached_func()); + }, 'list-style-image sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + async_test((t) => { const key = '{{uuid()}}'; const url = makeRequestURL(key, ['httpsOrigin', 'httpOrigin']); diff --git a/fetch/metadata/generated/element-a.https.sub.html b/fetch/metadata/generated/element-a.https.sub.html index dffd36c73ee373..6bc5069276145f 100644 --- a/fetch/metadata/generated/element-a.https.sub.html +++ b/fetch/metadata/generated/element-a.https.sub.html @@ -477,6 +477,46 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user - no attributes with user activation'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - no attributes'); diff --git a/fetch/metadata/generated/element-a.sub.html b/fetch/metadata/generated/element-a.sub.html index 0661de3c871bb4..389d3393b64509 100644 --- a/fetch/metadata/generated/element-a.sub.html +++ b/fetch/metadata/generated/element-a.sub.html @@ -276,6 +276,66 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination - no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-area.https.sub.html b/fetch/metadata/generated/element-area.https.sub.html index be3f5f9b621176..2355cceda09316 100644 --- a/fetch/metadata/generated/element-area.https.sub.html +++ b/fetch/metadata/generated/element-area.https.sub.html @@ -477,6 +477,46 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user - no attributes with user activation'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - no attributes'); diff --git a/fetch/metadata/generated/element-area.sub.html b/fetch/metadata/generated/element-area.sub.html index 5f5c338324f001..1932a66cc0991f 100644 --- a/fetch/metadata/generated/element-area.sub.html +++ b/fetch/metadata/generated/element-area.sub.html @@ -276,6 +276,66 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination - no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + { + test: t, + userActivated: false, + attributes: {} + } + ); + + // `induceRequest` does not necessarily trigger a navigation, so the Python + // handler must be polled until it has received the initial request. + return retrieve(key, {poll: true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-audio.https.sub.html b/fetch/metadata/generated/element-audio.https.sub.html index a9d951233e296f..f0ce53cbd151b0 100644 --- a/fetch/metadata/generated/element-audio.https.sub.html +++ b/fetch/metadata/generated/element-audio.https.sub.html @@ -320,6 +320,33 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-audio.sub.html b/fetch/metadata/generated/element-audio.sub.html index 2b62632ac2eb8c..efe9164c6d23c7 100644 --- a/fetch/metadata/generated/element-audio.sub.html +++ b/fetch/metadata/generated/element-audio.sub.html @@ -184,6 +184,45 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-embed.https.sub.html b/fetch/metadata/generated/element-embed.https.sub.html index 819bed888ee4cb..2aea58d0b4de6f 100644 --- a/fetch/metadata/generated/element-embed.https.sub.html +++ b/fetch/metadata/generated/element-embed.https.sub.html @@ -219,6 +219,27 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsCrossSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsSameSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/element-embed.sub.html b/fetch/metadata/generated/element-embed.sub.html index b6e14a55e4a549..e394d4d7f9acba 100644 --- a/fetch/metadata/generated/element-embed.sub.html +++ b/fetch/metadata/generated/element-embed.sub.html @@ -154,6 +154,36 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpOrigin'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpSameSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpCrossSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-frame.https.sub.html b/fetch/metadata/generated/element-frame.https.sub.html index 17504ff5635c4b..7df86fb7b4bdf7 100644 --- a/fetch/metadata/generated/element-frame.https.sub.html +++ b/fetch/metadata/generated/element-frame.https.sub.html @@ -304,6 +304,35 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user with user activation'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/element-frame.sub.html b/fetch/metadata/generated/element-frame.sub.html index 2d9a7ec97d7808..6a10ca2b34d7f7 100644 --- a/fetch/metadata/generated/element-frame.sub.html +++ b/fetch/metadata/generated/element-frame.sub.html @@ -202,6 +202,48 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-iframe.https.sub.html b/fetch/metadata/generated/element-iframe.https.sub.html index fba1c8b9e02f19..10de00614808d5 100644 --- a/fetch/metadata/generated/element-iframe.https.sub.html +++ b/fetch/metadata/generated/element-iframe.https.sub.html @@ -304,6 +304,35 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user with user activation'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/element-iframe.sub.html b/fetch/metadata/generated/element-iframe.sub.html index 6f71cc0d254737..5d2f096a3fabc7 100644 --- a/fetch/metadata/generated/element-iframe.sub.html +++ b/fetch/metadata/generated/element-iframe.sub.html @@ -202,6 +202,48 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + t, + false + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-img-environment-change.https.sub.html b/fetch/metadata/generated/element-img-environment-change.https.sub.html index a19aa117c4f46e..9e9c3723e9a5e7 100644 --- a/fetch/metadata/generated/element-img-environment-change.https.sub.html +++ b/fetch/metadata/generated/element-img-environment-change.https.sub.html @@ -352,6 +352,35 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsSameSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-img-environment-change.sub.html b/fetch/metadata/generated/element-img-environment-change.sub.html index 96658726ba0c91..0d99cb3171ba4b 100644 --- a/fetch/metadata/generated/element-img-environment-change.sub.html +++ b/fetch/metadata/generated/element-img-environment-change.sub.html @@ -222,6 +222,48 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpOrigin'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpSameSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpCrossSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-img.https.sub.html b/fetch/metadata/generated/element-img.https.sub.html index 51d6e082b0e336..5a0f2e4e2006a6 100644 --- a/fetch/metadata/generated/element-img.https.sub.html +++ b/fetch/metadata/generated/element-img.https.sub.html @@ -640,6 +640,64 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - srcset - no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - src - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - srcset - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - src - Same site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - srcset - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-img.sub.html b/fetch/metadata/generated/element-img.sub.html index 5a4b152c5525b3..23008791d7f9ee 100644 --- a/fetch/metadata/generated/element-img.sub.html +++ b/fetch/metadata/generated/element-img.sub.html @@ -364,6 +364,90 @@ }); }, 'sec-fetch-user - srcset - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - src - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - srcset - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - src - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - srcset - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - src - Not sent to non-trustworthy cross-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - srcset - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-input-image.https.sub.html b/fetch/metadata/generated/element-input-image.https.sub.html index 7fa674043e2517..b5537eec60e37b 100644 --- a/fetch/metadata/generated/element-input-image.https.sub.html +++ b/fetch/metadata/generated/element-input-image.https.sub.html @@ -224,6 +224,27 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(makeRequestURL(key, ['httpsCrossSite']), t) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(makeRequestURL(key, ['httpsSameSite']), t) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-input-image.sub.html b/fetch/metadata/generated/element-input-image.sub.html index fb2a146b199dba..6f8743633fa690 100644 --- a/fetch/metadata/generated/element-input-image.sub.html +++ b/fetch/metadata/generated/element-input-image.sub.html @@ -148,6 +148,36 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(makeRequestURL(key, ['httpOrigin']), t) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(makeRequestURL(key, ['httpSameSite']), t) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(makeRequestURL(key, ['httpCrossSite']), t) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-link-icon.https.sub.html b/fetch/metadata/generated/element-link-icon.https.sub.html index b2449607553e41..b41f0afe4a8db7 100644 --- a/fetch/metadata/generated/element-link-icon.https.sub.html +++ b/fetch/metadata/generated/element-link-icon.https.sub.html @@ -366,6 +366,37 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite'], params), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpsSameSite'], params), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site no attributes'); diff --git a/fetch/metadata/generated/element-link-icon.sub.html b/fetch/metadata/generated/element-link-icon.sub.html index e9226c190a5089..ea9ecb4ffe0ce2 100644 --- a/fetch/metadata/generated/element-link-icon.sub.html +++ b/fetch/metadata/generated/element-link-icon.sub.html @@ -228,6 +228,51 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpOrigin'], params), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpSameSite'], params), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpCrossSite'], params), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html b/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html index bdd684a2679968..16347abc825d19 100644 --- a/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html +++ b/fetch/metadata/generated/element-link-prefetch.https.optional.sub.html @@ -553,6 +553,37 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite']), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpsSameSite']), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site no attributes'); diff --git a/fetch/metadata/generated/element-link-prefetch.optional.sub.html b/fetch/metadata/generated/element-link-prefetch.optional.sub.html index c2244883cc9077..c938671760270d 100644 --- a/fetch/metadata/generated/element-link-prefetch.optional.sub.html +++ b/fetch/metadata/generated/element-link-prefetch.optional.sub.html @@ -223,6 +223,51 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpOrigin']), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpSameSite']), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + induceRequest( + t, + makeRequestURL(key, ['httpCrossSite']), + {} + ); + + return retrieve(key, {poll:true}) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html b/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html index 3a1a8eb49af62a..7f763d630a396e 100644 --- a/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html +++ b/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html @@ -271,6 +271,30 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/element-meta-refresh.optional.sub.html b/fetch/metadata/generated/element-meta-refresh.optional.sub.html index df3e92e2c8fdeb..c1f3ecbbf8604d 100644 --- a/fetch/metadata/generated/element-meta-refresh.optional.sub.html +++ b/fetch/metadata/generated/element-meta-refresh.optional.sub.html @@ -183,6 +183,42 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-picture.https.sub.html b/fetch/metadata/generated/element-picture.https.sub.html index ba6636a019a304..2de087218ac03e 100644 --- a/fetch/metadata/generated/element-picture.https.sub.html +++ b/fetch/metadata/generated/element-picture.https.sub.html @@ -991,6 +991,99 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - source[srcset] - no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + 'img', + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - img[src] - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + 'img', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - img[srcset] - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + 'source', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - source[srcset] - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + 'img', + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[src] - Same site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + 'img', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[srcset] - Same site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + 'source', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - source[srcset] - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-picture.sub.html b/fetch/metadata/generated/element-picture.sub.html index 64f851c682b466..f0e087483d59b4 100644 --- a/fetch/metadata/generated/element-picture.sub.html +++ b/fetch/metadata/generated/element-picture.sub.html @@ -575,6 +575,141 @@ }); }, 'sec-fetch-user - source[srcset] - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + 'img', + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[src] - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + 'img', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[srcset] - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + 'source', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - source[srcset] - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + 'img', + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[src] - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + 'img', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[srcset] - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + 'source', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - source[srcset] - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + 'img', + 'src', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[src] - Not sent to non-trustworthy cross-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + 'img', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - img[srcset] - Not sent to non-trustworthy cross-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + 'source', + 'srcset', + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - source[srcset] - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-script.https.sub.html b/fetch/metadata/generated/element-script.https.sub.html index dcdcba2792d5c3..e52b165b74744d 100644 --- a/fetch/metadata/generated/element-script.https.sub.html +++ b/fetch/metadata/generated/element-script.https.sub.html @@ -589,5 +589,36 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsCrossSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsSameSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-script.sub.html b/fetch/metadata/generated/element-script.sub.html index a2526698fbdaa4..47ed5fa9f8faae 100644 --- a/fetch/metadata/generated/element-script.sub.html +++ b/fetch/metadata/generated/element-script.sub.html @@ -391,6 +391,96 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, attributes: type=module'); + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpOrigin'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpOrigin'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {"type": "module"} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, attributes: type=module'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpSameSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpSameSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {"type": "module"} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, attributes: type=module'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpCrossSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpCrossSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url, + {"type": "module"} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, attributes: type=module'); + promise_test(() => { const key = '{{uuid()}}'; const url = makeRequestURL( diff --git a/fetch/metadata/generated/element-video-poster.https.sub.html b/fetch/metadata/generated/element-video-poster.https.sub.html index 5805b46bd0cd67..ddd870af7c2ac1 100644 --- a/fetch/metadata/generated/element-video-poster.https.sub.html +++ b/fetch/metadata/generated/element-video-poster.https.sub.html @@ -238,6 +238,27 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsCrossSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpsSameSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/element-video-poster.sub.html b/fetch/metadata/generated/element-video-poster.sub.html index e6cc5ee7e0695d..aeb3d4f9b5e8e1 100644 --- a/fetch/metadata/generated/element-video-poster.sub.html +++ b/fetch/metadata/generated/element-video-poster.sub.html @@ -162,6 +162,36 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpOrigin'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpSameSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest(t, makeRequestURL(key, ['httpCrossSite'], params)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/element-video.https.sub.html b/fetch/metadata/generated/element-video.https.sub.html index 971360dceea4a0..c900807820c692 100644 --- a/fetch/metadata/generated/element-video.https.sub.html +++ b/fetch/metadata/generated/element-video.https.sub.html @@ -320,6 +320,33 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, no attributes'); diff --git a/fetch/metadata/generated/element-video.sub.html b/fetch/metadata/generated/element-video.sub.html index 9707413ab68b17..bf357e9da0e682 100644 --- a/fetch/metadata/generated/element-video.sub.html +++ b/fetch/metadata/generated/element-video.sub.html @@ -184,6 +184,45 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no attributes'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no attributes'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html b/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html index 22f930960d6d3d..c3b0599b9da767 100644 --- a/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html +++ b/fetch/metadata/generated/fetch-via-serviceworker.https.sub.html @@ -678,6 +678,68 @@ }); }, 'sec-fetch-user - no init - fallback'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite']), + {"credentials": "include", "mode": "no-cors"}, + 'respondWith' + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, init: mode=no-cors, credentials=include - respondWith'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite']), + {"credentials": "include", "mode": "no-cors"}, + 'fallback' + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, init: mode=no-cors, credentials=include - fallback'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsSameSite']), + {"credentials": "include", "mode": "no-cors"}, + 'respondWith' + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, init: mode=no-cors, credentials=include - respondWith'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsSameSite']), + {"credentials": "include", "mode": "no-cors"}, + 'fallback' + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, init: mode=no-cors, credentials=include - fallback'); + diff --git a/fetch/metadata/generated/fetch.https.sub.html b/fetch/metadata/generated/fetch.https.sub.html index dde1daede4ec3c..486f404d4bdf42 100644 --- a/fetch/metadata/generated/fetch.https.sub.html +++ b/fetch/metadata/generated/fetch.https.sub.html @@ -297,6 +297,33 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - no init'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite']), + {"credentials": "include", "mode": "no-cors"} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site, init: mode=no-cors, credentials=include'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite']), + {"credentials": "include", "mode": "no-cors"} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site, init: mode=no-cors, credentials=include'); diff --git a/fetch/metadata/generated/fetch.sub.html b/fetch/metadata/generated/fetch.sub.html index d28ea9bb9004f2..7d9536efcfbdfe 100644 --- a/fetch/metadata/generated/fetch.sub.html +++ b/fetch/metadata/generated/fetch.sub.html @@ -175,6 +175,45 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination, no init'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no init'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination, no init'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite']), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination, no init'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/form-submission.https.sub.html b/fetch/metadata/generated/form-submission.https.sub.html index 988b07c74a948f..0935f8461118d9 100644 --- a/fetch/metadata/generated/form-submission.https.sub.html +++ b/fetch/metadata/generated/form-submission.https.sub.html @@ -517,6 +517,50 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user - POST with user activation'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + const userActivated = false; + return induceRequest('GET', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - GET'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + const userActivated = false; + return induceRequest('POST', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - POST'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + const userActivated = false; + return induceRequest('GET', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - GET'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + const userActivated = false; + return induceRequest('POST', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - POST'); diff --git a/fetch/metadata/generated/form-submission.sub.html b/fetch/metadata/generated/form-submission.sub.html index f862062aebcd30..b0f56f609429ad 100644 --- a/fetch/metadata/generated/form-submission.sub.html +++ b/fetch/metadata/generated/form-submission.sub.html @@ -326,6 +326,72 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination - POST'); + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + const userActivated = false; + return induceRequest('GET', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - GET'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + const userActivated = false; + return induceRequest('POST', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - POST'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + const userActivated = false; + return induceRequest('GET', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - GET'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + const userActivated = false; + return induceRequest('POST', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - POST'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + const userActivated = false; + return induceRequest('GET', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - GET'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + const userActivated = false; + return induceRequest('POST', url, userActivated) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - POST'); + promise_test(() => { const key = '{{uuid()}}'; const url = makeRequestURL(key, ['httpsOrigin', 'httpOrigin'], responseParams); diff --git a/fetch/metadata/generated/header-link.https.sub.html b/fetch/metadata/generated/header-link.https.sub.html index 09f011389559bf..8e7d029dc25287 100644 --- a/fetch/metadata/generated/header-link.https.sub.html +++ b/fetch/metadata/generated/header-link.https.sub.html @@ -524,6 +524,64 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user rel=stylesheet'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + 'icon', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access rel=icon - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], {mime: 'text/html'}), + 'stylesheet', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access rel=stylesheet - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + 'icon', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=icon - Same site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], {mime: 'text/html'}), + 'stylesheet', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=stylesheet - Same site'); diff --git a/fetch/metadata/generated/header-link.sub.html b/fetch/metadata/generated/header-link.sub.html index 8b6cdae0edad7b..b0823071345e8f 100644 --- a/fetch/metadata/generated/header-link.sub.html +++ b/fetch/metadata/generated/header-link.sub.html @@ -368,6 +368,90 @@ }); }, 'sec-fetch-user rel=stylesheet - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + 'icon', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=icon - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], {mime: 'text/html'}), + 'stylesheet', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=stylesheet - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + 'icon', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=icon - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], {mime: 'text/html'}), + 'stylesheet', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=stylesheet - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + 'icon', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=icon - Not sent to non-trustworthy cross-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], {mime: 'text/html'}), + 'stylesheet', + t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access rel=stylesheet - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/header-refresh.https.optional.sub.html b/fetch/metadata/generated/header-refresh.https.optional.sub.html index e63ee423cd74a9..0f7e9e42b79b39 100644 --- a/fetch/metadata/generated/header-refresh.https.optional.sub.html +++ b/fetch/metadata/generated/header-refresh.https.optional.sub.html @@ -268,6 +268,30 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsCrossSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpsSameSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/header-refresh.optional.sub.html b/fetch/metadata/generated/header-refresh.optional.sub.html index 4674ada9c6da15..873013e821c225 100644 --- a/fetch/metadata/generated/header-refresh.optional.sub.html +++ b/fetch/metadata/generated/header-refresh.optional.sub.html @@ -180,6 +180,42 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpOrigin'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpSameSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL(key, ['httpCrossSite'], responseParams), t + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/script-module-import-dynamic.https.sub.html b/fetch/metadata/generated/script-module-import-dynamic.https.sub.html index 72d60fc30cb5f0..94ef41b9228dfe 100644 --- a/fetch/metadata/generated/script-module-import-dynamic.https.sub.html +++ b/fetch/metadata/generated/script-module-import-dynamic.https.sub.html @@ -250,5 +250,31 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsCrossSite'], { mime: 'application/javascript' } + ); + + return import(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsSameSite'], { mime: 'application/javascript' } + ); + + return import(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/script-module-import-dynamic.sub.html b/fetch/metadata/generated/script-module-import-dynamic.sub.html index 088720c23e0db4..16aefa11176bac 100644 --- a/fetch/metadata/generated/script-module-import-dynamic.sub.html +++ b/fetch/metadata/generated/script-module-import-dynamic.sub.html @@ -170,6 +170,45 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpOrigin'], { mime: 'application/javascript' } + ); + + return import(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpSameSite'], { mime: 'application/javascript' } + ); + + return import(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpCrossSite'], { mime: 'application/javascript' } + ); + + return import(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { const key = '{{uuid()}}'; const url = makeRequestURL( diff --git a/fetch/metadata/generated/script-module-import-static.https.sub.html b/fetch/metadata/generated/script-module-import-static.https.sub.html index cea3464f80701a..62968f318f5f5c 100644 --- a/fetch/metadata/generated/script-module-import-static.https.sub.html +++ b/fetch/metadata/generated/script-module-import-static.https.sub.html @@ -284,5 +284,33 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL( + key, ['httpsCrossSite'], { mime: 'application/javascript' } + ) + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL( + key, ['httpsSameSite'], { mime: 'application/javascript' } + ) + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/script-module-import-static.sub.html b/fetch/metadata/generated/script-module-import-static.sub.html index 0f94f71cf6f186..c4da15766067b8 100644 --- a/fetch/metadata/generated/script-module-import-static.sub.html +++ b/fetch/metadata/generated/script-module-import-static.sub.html @@ -199,6 +199,48 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL( + key, ['httpOrigin'], { mime: 'application/javascript' } + ) + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL( + key, ['httpSameSite'], { mime: 'application/javascript' } + ) + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + + return induceRequest( + makeRequestURL( + key, ['httpCrossSite'], { mime: 'application/javascript' } + ) + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/svg-image.https.sub.html b/fetch/metadata/generated/svg-image.https.sub.html index b059eb31456dfc..9dd0da15f9d310 100644 --- a/fetch/metadata/generated/svg-image.https.sub.html +++ b/fetch/metadata/generated/svg-image.https.sub.html @@ -362,6 +362,35 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsCrossSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpsSameSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site no attributes'); diff --git a/fetch/metadata/generated/svg-image.sub.html b/fetch/metadata/generated/svg-image.sub.html index a28bbb12eb71ec..56427bedaa68e3 100644 --- a/fetch/metadata/generated/svg-image.sub.html +++ b/fetch/metadata/generated/svg-image.sub.html @@ -217,6 +217,48 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpOrigin'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpSameSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination no attributes'); + + promise_test((t) => { + const key = '{{uuid()}}'; + + return induceRequest( + t, + makeRequestURL(key, ['httpCrossSite'], params), + {} + ) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination no attributes'); + promise_test((t) => { const key = '{{uuid()}}'; diff --git a/fetch/metadata/generated/window-history.https.sub.html b/fetch/metadata/generated/window-history.https.sub.html index c2b3079a6d3670..64e282e778945e 100644 --- a/fetch/metadata/generated/window-history.https.sub.html +++ b/fetch/metadata/generated/window-history.https.sub.html @@ -232,6 +232,50 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - history.forward'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + return induceBackRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - history.back'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + return induceForwardRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - history.forward'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + return induceBackRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - history.back'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + return induceForwardRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - history.forward'); diff --git a/fetch/metadata/generated/window-history.sub.html b/fetch/metadata/generated/window-history.sub.html index 333d90c28609bd..836704964773b5 100644 --- a/fetch/metadata/generated/window-history.sub.html +++ b/fetch/metadata/generated/window-history.sub.html @@ -355,6 +355,72 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination - history.forward'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + return induceBackRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - history.back'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + return induceForwardRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - history.forward'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + return induceBackRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - history.back'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + return induceForwardRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - history.forward'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + return induceBackRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - history.back'); + + promise_test((t) => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + return induceForwardRequest(url, t, () => retrieve(key)) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - history.forward'); diff --git a/fetch/metadata/generated/window-location.https.sub.html b/fetch/metadata/generated/window-location.https.sub.html index 4a0d2fdc068078..387039bcf25627 100644 --- a/fetch/metadata/generated/window-location.https.sub.html +++ b/fetch/metadata/generated/window-location.https.sub.html @@ -1179,6 +1179,118 @@ assert_array_equals(headers['sec-fetch-user'], ['?1']); }); }, 'sec-fetch-user - location.replace with user activation'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - location'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.href = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - location.href'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.assign(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - location.assign'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.replace(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Cross-site - location.replace'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + const navigate = (win, path) => { + win.location = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - location'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.href = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - location.href'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.assign(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - location.assign'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpsSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.replace(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site - location.replace'); diff --git a/fetch/metadata/generated/window-location.sub.html b/fetch/metadata/generated/window-location.sub.html index bb3e6805cb0114..e307b909dce182 100644 --- a/fetch/metadata/generated/window-location.sub.html +++ b/fetch/metadata/generated/window-location.sub.html @@ -714,6 +714,174 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination - location.replace'); + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + const navigate = (win, path) => { + win.location = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - location'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + const navigate = (win, path) => { + win.location.href = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - location.href'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + const navigate = (win, path) => { + win.location.assign(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - location.assign'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpOrigin'], responseParams); + + const navigate = (win, path) => { + win.location.replace(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination - location.replace'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + const navigate = (win, path) => { + win.location = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - location'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.href = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - location.href'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.assign(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - location.assign'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpSameSite'], responseParams); + + const navigate = (win, path) => { + win.location.replace(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination - location.replace'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - location'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.href = path; + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - location.href'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.assign(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - location.assign'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL(key, ['httpCrossSite'], responseParams); + + const navigate = (win, path) => { + win.location.replace(path); + }; + return induceRequest(url, navigate, false) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination - location.replace'); + promise_test(() => { const key = '{{uuid()}}'; const url = makeRequestURL(key, ['httpsOrigin', 'httpOrigin'], responseParams); diff --git a/fetch/metadata/generated/worker-dedicated-constructor.sub.html b/fetch/metadata/generated/worker-dedicated-constructor.sub.html index 65b1837c6363a2..e05e12df3959da 100644 --- a/fetch/metadata/generated/worker-dedicated-constructor.sub.html +++ b/fetch/metadata/generated/worker-dedicated-constructor.sub.html @@ -80,5 +80,20 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user - Not sent to non-trustworthy same-origin destination, no options'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, + ['httpOrigin'], + { mime: 'application/javascript', body: 'postMessage("")' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination, no options'); diff --git a/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html b/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html index 0cd9f35d582535..5b48e59e716b90 100644 --- a/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html +++ b/fetch/metadata/generated/worker-dedicated-importscripts.https.sub.html @@ -264,5 +264,32 @@ assert_not_own_property(headers, 'sec-fetch-user'); }); }, 'sec-fetch-user'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsCrossSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_own_property(headers, 'sec-fetch-storage-access'); + assert_array_equals(headers['sec-fetch-storage-access'], ['none']); + }); + }, 'sec-fetch-storage-access - Cross-site'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpsSameSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Same site'); diff --git a/fetch/metadata/generated/worker-dedicated-importscripts.sub.html b/fetch/metadata/generated/worker-dedicated-importscripts.sub.html index 0555bbaf432696..ad4792b8a60c42 100644 --- a/fetch/metadata/generated/worker-dedicated-importscripts.sub.html +++ b/fetch/metadata/generated/worker-dedicated-importscripts.sub.html @@ -184,6 +184,45 @@ }); }, 'sec-fetch-user - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpOrigin'], { mime: 'application/javascript' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpSameSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy same-site destination'); + + promise_test(() => { + const key = '{{uuid()}}'; + const url = makeRequestURL( + key, ['httpCrossSite'], { mime: 'application/javascript' } + ); + + return induceRequest(url) + .then(() => retrieve(key)) + .then((headers) => { + assert_not_own_property(headers, 'sec-fetch-storage-access'); + }); + }, 'sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination'); + promise_test(() => { const key = '{{uuid()}}'; const url = makeRequestURL( diff --git a/fetch/metadata/tools/fetch-metadata.conf.yml b/fetch/metadata/tools/fetch-metadata.conf.yml index b96bd2fd7b4b81..bc764aed02de4c 100644 --- a/fetch/metadata/tools/fetch-metadata.conf.yml +++ b/fetch/metadata/tools/fetch-metadata.conf.yml @@ -42,6 +42,15 @@ cases: - headerName: sec-fetch-user origins: [httpCrossSite] description: Not sent to non-trustworthy cross-site destination + - headerName: sec-fetch-storage-access + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-storage-access + origins: [httpSameSite] + description: Not sent to non-trustworthy same-site destination + - headerName: sec-fetch-storage-access + origins: [httpCrossSite] + description: Not sent to non-trustworthy cross-site destination template_axes: # The `AudioWorklet` interface is only available in secure contexts # https://webaudio.github.io/web-audio-api/#AudioWorklet @@ -109,6 +118,9 @@ cases: - headerName: sec-fetch-user origins: [httpOrigin] description: Not sent to non-trustworthy same-origin destination + - headerName: sec-fetch-storage-access + origins: [httpOrigin] + description: Not sent to non-trustworthy same-origin destination template_axes: # All the templates in this block are unused with the exception of # `worker-dedicated-constructor` @@ -848,3 +860,72 @@ cases: expected: NULL worker-dedicated-importscripts.sub.html: - expected: NULL + # Sec-Fetch-Storage-Access + - all_subtests: + headerName: sec-fetch-storage-access + filename_flags: [https] + common_axis: + - description: Cross-site + origins: [httpsCrossSite] + expected: none + - description: Same site + origins: [httpsSameSite] + expected: NULL + template_axes: + # Service Workers' redirect mode is "error" + serviceworker.https.sub.html: [{}] + # Interstitial locations in an HTTP redirect chain are not added to the + # session history, so these requests cannot be initiated using the + # History API. + css-images.sub.html: + - filename_flags: [tentative] + element-audio.sub.html: [{}] + element-embed.sub.html: [{}] + element-frame.sub.html: [{}] + element-iframe.sub.html: [{}] + element-img.sub.html: + - sourceAttr: src + - sourceAttr: srcset + element-img-environment-change.sub.html: [{}] + element-input-image.sub.html: [{}] + element-link-icon.sub.html: [{}] + element-link-prefetch.optional.sub.html: [{}] + element-picture.sub.html: [{}] + element-script.sub.html: [{}] + element-video.sub.html: [{}] + element-video-poster.sub.html: [{}] + fetch.sub.html: [{ init: { mode: no-cors , credentials: include } }] + fetch-via-serviceworker.https.sub.html: [{ init: { mode: no-cors , credentials: include } }] + header-link.sub.html: + - rel: icon + - rel: stylesheet + svg-image.sub.html: [{}] + worker-dedicated-constructor.sub.html: [] + worker-dedicated-importscripts.sub.html: [{}] + # The following are cases where the Sec-Fetch-Storage-Access header should + # not be attached at all. + - all_subtests: + headerName: sec-fetch-storage-access + filename_flags: [https] + common_axis: + - description: Cross-site + origins: [httpsCrossSite] + expected: NULL + - description: Same site + origins: [httpsSameSite] + expected: NULL + template_axes: + audioworklet.https.sub.html: [{}] + css-font-face.sub.html: + - filename_flags: [tentative] + element-meta-refresh.optional.sub.html: [{}] + element-a.sub.html: [{}] + element-area.sub.html: [{}] + form-submission.sub.html: + - method: GET + - method: POST + header-refresh.optional.sub.html: [{}] + script-module-import-dynamic.sub.html: [{}] + script-module-import-static.sub.html: [{}] + window-history.sub.html: [{}] + window-location.sub.html: [{}] diff --git a/storage-access-api/helpers.js b/storage-access-api/helpers.js index a1fd02ab5e60b8..a698fac6491a17 100644 --- a/storage-access-api/helpers.js +++ b/storage-access-api/helpers.js @@ -279,12 +279,19 @@ function FetchFromFrame(frame, url) { // Makes a subresource request to the provided host in the given frame with // the mode set to 'no-cors' -function NoCorsSubresourceCookiesFromFrame(frame, host) { - const url = `${host}/storage-access-api/resources/echo-cookie-header.py`; +function NoCorsFetchFromFrame(frame, url) { return PostMessageAndAwaitReply( { command: "no-cors fetch", url }, frame.contentWindow); } +// Makes a subresource request to the provided host in the given frame with +// the mode set to 'no-cors', and returns the cookies that were included in the +// request. +function NoCorsSubresourceCookiesFromFrame(frame, host) { + const url = `${host}/storage-access-api/resources/echo-cookie-header.py`; + return NoCorsFetchFromFrame(frame, url); +} + // Tries to set storage access policy, ignoring any errors. // // Note: to discourage the writing of tests that assume unpartitioned cookie diff --git a/storage-access-api/resources/handle-headers-non-retry.py b/storage-access-api/resources/handle-headers-non-retry.py new file mode 100644 index 00000000000000..b4b3c0ec83b33e --- /dev/null +++ b/storage-access-api/resources/handle-headers-non-retry.py @@ -0,0 +1,20 @@ +import importlib +header_helpers = importlib.import_module("storage-access-api.resources.header-helpers") + +def main(request, response): + request_params = request.GET + if b'key' in request_params: + key = request_params.first(b'key') + # Do not handle requests without a key parameter. + else: + return (400, [], b'') + + # Handle load requests. + if b'load' in request_params: + response.headers.set(b'Activate-Storage-Access', b'load') + + request.server.stash.put(header_helpers.make_stash_key(key, request_params), + header_helpers.get_stashable_headers(request.headers), + header_helpers.RETRIEVAL_PATH) + + return header_helpers.make_response_body(request_params) \ No newline at end of file diff --git a/storage-access-api/resources/handle-headers-retry.py b/storage-access-api/resources/handle-headers-retry.py new file mode 100644 index 00000000000000..ca079489b18361 --- /dev/null +++ b/storage-access-api/resources/handle-headers-retry.py @@ -0,0 +1,43 @@ +import importlib +header_helpers = importlib.import_module("storage-access-api.resources.header-helpers") + +# Sets the `Activate-Storage-Access` response header to a `retry` value +# corresponding to the supplied `allowed_origin`. +def maybe_set_retry(allowed_origin, response): + if allowed_origin is None: + return + + if allowed_origin == b'*': + retry_response = b'retry; allowed-origin=*' + elif allowed_origin == b'': + retry_response = b'retry' + else: + retry_response = b'retry; allowed-origin=\"' + allowed_origin + b'\"' + response.headers.set(b'Activate-Storage-Access', retry_response) + +def main(request, response): + request_params = request.GET + if b'key' in request_params: + key = request_params.first(b'key') + # Do not handle requests without a key parameter. + else: + return (400, [], b'') + + allowed_origin = request_params.first(b'retry-allowed-origin', None) + storage_access_status = request.headers.get(b'sec-fetch-storage-access') + + # If a request has been successfully retried and set to active, store its + # headers under a modified key so they can be retrieved independently of + # the initial request's headers. + if storage_access_status == b'active': + key += b'active' + maybe_set_retry(allowed_origin, response) + + # Check if the request should redirect. + header_helpers.maybe_set_redirect(request_params, response, storage_access_status) + + request.server.stash.put(header_helpers.make_stash_key(key, request_params), + header_helpers.get_stashable_headers(request.headers), + header_helpers.RETRIEVAL_PATH) + + return header_helpers.make_response_body(request_params) \ No newline at end of file diff --git a/storage-access-api/resources/header-helpers.py b/storage-access-api/resources/header-helpers.py new file mode 100644 index 00000000000000..6909fd896ede88 --- /dev/null +++ b/storage-access-api/resources/header-helpers.py @@ -0,0 +1,58 @@ +import hashlib +import json + +RETRIEVAL_PATH = '/storage-access-api/resources/retrieve-storage-access-headers.py' + +def get_stashable_headers(headers): + def bytes_to_strings(d): + # Recursively convert bytes to strings in `d`. + if isinstance(d, (tuple,list,set)): + return [bytes_to_strings(x) for x in d] + elif isinstance(d, bytes): + return d.decode() + elif isinstance(d, dict): + return {bytes_to_strings(k): bytes_to_strings(v) for (k, v) in d.items()} + return d + return json.dumps(bytes_to_strings(headers)) + +# Makes a string representation of the hash generated for the given key. +def make_stash_key(key, request_params): + # Redirected requests stash their headers at a different key. + key += b'redirected' if b'redirected' in request_params else b'' + return hashlib.md5(key).hexdigest() + +# Sets the response to redirect to the location passed by the request if its +# parameters contain a `redirect-location` or a `once-active-redirect-location` +# with an active `storage_access_status`. +def maybe_set_redirect(request_params, response, storage_access_status): + if storage_access_status == b'active': + location = request_params.first(b'once-active-redirect-location', '') + else: + location = request_params.first(b'redirect-location', '') + + if location: + response.status = 302 + response.headers.set(b'Location', location) + +# Returns an HTML body with an embedded responder if one is included in +# `request_params`, otherwise returns an empty byte-string. +def make_response_body(request_params): + script = request_params.first(b'script', None) + if script is None: + return b'' + return b""" + + + Subframe with script + + + + + + + + + + """ % (script) \ No newline at end of file diff --git a/storage-access-api/resources/nested-handle-storage-access-headers.py b/storage-access-api/resources/nested-handle-storage-access-headers.py new file mode 100644 index 00000000000000..db0bf34357382e --- /dev/null +++ b/storage-access-api/resources/nested-handle-storage-access-headers.py @@ -0,0 +1,5 @@ +import importlib +header_helpers = importlib.import_module("storage-access-api.resources.header-helpers") + +def main(request, response): + return header_helpers.make_response_body(request.GET) diff --git a/storage-access-api/resources/retrieve-storage-access-headers.py b/storage-access-api/resources/retrieve-storage-access-headers.py new file mode 100644 index 00000000000000..553c0c6dd4a6c1 --- /dev/null +++ b/storage-access-api/resources/retrieve-storage-access-headers.py @@ -0,0 +1,17 @@ +import hashlib + +def main(request, response): + if b'key' in request.GET: + key = request.GET.first(b'key') + # Do not handle requests without a key parameter. + else: + return (400, [], b'') + + # Convert the key from String to UUID valid String. + stash_key = hashlib.md5(key).hexdigest() + + # Handle the header retrieval request. + headers = request.server.stash.take(stash_key) + if headers is None: + return (204, [], b'') + return (200, [], headers) diff --git a/storage-access-api/storage-access-headers.tentative.https.sub.window.js b/storage-access-api/storage-access-headers.tentative.https.sub.window.js new file mode 100644 index 00000000000000..10719750174492 --- /dev/null +++ b/storage-access-api/storage-access-headers.tentative.https.sub.window.js @@ -0,0 +1,487 @@ +// META: script=helpers.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +"use strict"; + +// These are secure origins with different relations to the current document. +const https_origin = 'https://{{host}}:{{ports[https][0]}}'; +const same_site = 'https://{{hosts[][www]}}:{{ports[https][0]}}'; +const cross_site = 'https://{{hosts[alt][]}}:{{ports[https][0]}}'; +const alt_cross_site = 'https://{{hosts[alt][www]}}:{{ports[https][0]}}'; + +const responder_script = 'embedded_responder.js'; +const nested_path = '/storage-access-api/resources/nested-handle-storage-access-headers.py'; +const retry_path = '/storage-access-api/resources/handle-headers-retry.py'; +const non_retry_path = '/storage-access-api/resources/handle-headers-non-retry.py'; + +function makeURL(key, domain, path, params) { + const request_params = new URLSearchParams(params); + request_params.append('key', key); + return domain + path + '?' + request_params.toString(); +} + +async function grantStorageAccessForEmbedSite(test, origin) { + const iframe_params = new URLSearchParams([['script', responder_script]]); + const iframe = await CreateFrame(origin + + '/storage-access-api/resources/script-with-cookie-header.py?' + + iframe_params.toString()); + test.add_cleanup( async () => { + await SetPermissionInFrame(iframe, + [{ name: 'storage-access' }, 'prompt']); + iframe.parentNode.removeChild(iframe); + }) + await SetPermissionInFrame(iframe, + [{ name: 'storage-access' }, 'granted']); +} + +// Sends a request whose headers can be read in cross-site contexts. +async function sendReadableHeaderRequest(url) { + return fetch(url, {credentials: 'include', mode: 'no-cors'}); +} + +// Sends a request `resources/retrieve-storage-access-headers.py` and parses +// the response as JSON. Will return `undefined` if no headers were set at the +// given key, or if the headers have already been retrieved from that key. +async function sendRetrieveRequest(key) { + const retrieval_path = '/storage-access-api/resources/retrieve-storage-access-headers.py?'; + const request_params = new URLSearchParams([['key', key]]); + const response = await fetch(retrieval_path + request_params.toString()); + + return response.status !== 200 ? undefined : response.json(); +} + +// Checks that the values of `actual_headers` match those passed in the +// `expected_headers` at their respective header keys. Headers with the value +// of `undefined` in `expected_headers` are expected to be absent from +// `actual_headers`. +function assertHeaderValuesMatch(actual_headers, expected_headers) { + for (const [expected_name, expected_value] of Object.entries( + expected_headers)) { + const actual_value = actual_headers[expected_name]; + if (expected_value === undefined) { + assert_equals(actual_value, undefined); + } else { + assert_array_equals(actual_value, expected_value); + } + } +} + +function addCommonCleanupCallback(test) { + test.add_cleanup(async () => { + await test_driver.delete_all_cookies(); + await MaybeSetStorageAccess("*", "*", "allowed"); + }); +} + +function retriedKey(key) { + return key + 'active'; +} + +function redirectedKey(key) { + return key + 'redirected'; +} + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await fetch(makeURL(key, cross_site, non_retry_path), + {credentials: 'omit', mode: 'no-cors'}); + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': undefined}); +}, "Sec-Fetch-Storage-Access is omitted when credentials are omitted"); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await sendReadableHeaderRequest(makeURL(key, cross_site, non_retry_path)); + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['none']}); +}, "Sec-Fetch-Storage-Access is `none` when unpartitioned cookies are unavailable."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + + // Create an iframe and grant it storage access permissions. + await grantStorageAccessForEmbedSite(t, cross_site); + // A cross-site request to the same site as the above iframe should have an + // `inactive` storage access status since a permission grant exists for the + // context. + await sendReadableHeaderRequest(makeURL(key, cross_site, non_retry_path)); + const headers = await sendRetrieveRequest(key); + // We should see the origin header on the inactive case. + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin]}); +}, "Sec-Fetch-Storage-Access is `inactive` when unpartitioned cookies are available but not in use."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin]])); + // Retrieve the pre-retry headers. + const headers = await sendRetrieveRequest(key); + // Unpartitioned cookie should not be included before the retry. + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], 'cookie': undefined}); + // Retrieve the headers for the retried request. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + // The unpartitioned cookie should have been included in the retry. + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); +}, "Sec-Fetch-Storage-Access is `active` after a valid retry with matching explicit allowed-origin."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin','*']])); + // Retrieve the pre-retry headers. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, { + 'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], + 'cookie': undefined + }); + // Retrieve the headers for the retried request. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); +}, "Sec-Fetch-Storage-Access is active after retry with wildcard `allowed-origin` value."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + await sendReadableHeaderRequest( + makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', '']])); + + // The server behavior when retrieving a header that was never sent is + // indistinguishable from its behavior when retrieving a header that was + // sent but was previously retrieved. To ensure the request to retrieve the + // post-retry header occurs only because they were never sent, always + // test its retrieval first. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assert_equals(retried_headers, undefined); + // Retrieve the pre-retry headers. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive']}); +}, "'Activate-Storage-Access: retry' is a no-op on a request without an `allowed-origin` value."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + same_site]])); + // Should not be able to retrieve any headers at the post-retry key. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assert_equals(retried_headers, undefined); + // Retrieve the pre-retry headers. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive']}); +}, "'Activate-Storage-Access: retry' is a no-op on a request from an origin that does not match its `allowed-origin` value."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin]])); + // Should not be able to retrieve any headers at the post-retry key. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assert_equals(retried_headers, undefined); + // Retrieve the pre-retry headers. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['none'], + 'origin': undefined}); +}, "Activate-Storage-Access `retry` is a no-op on a request with a `none` Storage Access status."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + const load_header_iframe = await CreateFrame(makeURL(key, cross_site, + non_retry_path, + [['load', ''], + ['script', responder_script]])); + assert_true(await FrameHasStorageAccess(load_header_iframe), + "frame should have storage access because of the `load` header"); +}, "Activate-Storage-Access `load` header grants storage access to frame."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + const iframe = await CreateFrame(makeURL(key, cross_site, + non_retry_path, + [['script', responder_script]])); + t.add_cleanup(async () => { + SetPermissionInFrame(iframe, + [{ name: 'storage-access' }, 'prompt']); + }); + await SetPermissionInFrame(iframe, + [{ name: 'storage-access' }, 'granted']); + await RequestStorageAccessInFrame(iframe); + // Create a child iframe with the same source, that causes the server to + // respond with the `load` header. + const nested_iframe = await CreateFrameHelper((frame) => { + // Need a unique `key` on the request or else the server will fail it. + frame.src = makeURL(key + 'load', cross_site, non_retry_path, + [['load', ''], ['script', responder_script]]); + iframe.appendChild(frame); + }, false); + // The nested frame will have storage access because of the `load` response. + assert_true(await FrameHasStorageAccess(nested_iframe)); +}, "Activate-Storage-Access `load` is honored for `active` cases."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + addCommonCleanupCallback(t); + + const load_header_iframe = await CreateFrame(makeURL(key, cross_site, + non_retry_path, + [['load', ''], + ['script', responder_script]])); + assert_false(await FrameHasStorageAccess(load_header_iframe), + "frame should not have received storage access."); +}, "Activate-Storage-Access `load` header is a no-op for requests without storage access."); + +promise_test(async t => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess('*', '*', 'blocked'); + addCommonCleanupCallback(t); + + const iframe_params = new URLSearchParams([['script', + 'embedded_responder.js']]); + const iframe = await CreateFrame(cross_site + nested_path + '?' + + iframe_params.toString()); + + // Create a cross-site request within the iframe + const nested_url_params = new URLSearchParams([['key', key]]); + const nested_url = https_origin + non_retry_path + '?' + + nested_url_params.toString(); + await NoCorsFetchFromFrame(iframe, nested_url); + + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive'], + 'origin': [cross_site]}); +}, "Sec-Fetch-Storage-Access is `inactive` for ABA case."); + +promise_test(async t => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess('*', '*', 'blocked'); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(https_origin); + addCommonCleanupCallback(t); + + const iframe_params = new URLSearchParams([['script', + 'embedded_responder.js']]); + const iframe = await CreateFrame(cross_site + nested_path + '?' + + iframe_params.toString()); + + const nested_url_params = new URLSearchParams([ + ['key', key], + ['retry-allowed-origin', cross_site]]); + const nested_url = https_origin + retry_path + + '?' + nested_url_params.toString(); + await NoCorsFetchFromFrame(iframe, nested_url); + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, { + 'sec-fetch-storage-access': ['inactive'], + 'origin': [cross_site], + 'cookie': undefined + }); + + // Storage access should have been activated, without the need for a grant, + // on the ABA case. + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [cross_site], + 'cookie': ['cookie=unpartitioned'] + }); +}, "Storage Access can be activated for ABA cases by retrying."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + + // Create a redirect destination that is same origin to the initial + // request. + const redirect_url = makeURL(key, + cross_site, + retry_path, + [['redirected', '']]); + // Send a request instructing the server include the `retry` response, + // and then redirect when storage access has been activated. + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin], + ['once-active-redirect-location', + redirect_url]])); + // Confirm the normal retry behavior. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], 'cookie': undefined}); + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); + // Retrieve the headers for the post-retry redirect request. + const redirected_headers = await sendRetrieveRequest(redirectedKey(retriedKey(key))); + assertHeaderValuesMatch(redirected_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); +}, "Sec-Fetch-Storage-Access maintains value on same-origin redirect."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + + await grantStorageAccessForEmbedSite(t, cross_site); + + // Create a redirect destination that is cross-origin same-site to the + // initial request. + const redirect_url = makeURL(key, alt_cross_site, retry_path, + [['redirected', '']]); + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin], + ['once-active-redirect-location', + redirect_url]])); + + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, { + 'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], + 'cookie': undefined + }); + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); + // Retrieve the headers for the post-retry redirect request. + const redirected_headers = await sendRetrieveRequest(redirectedKey(key)); + assertHeaderValuesMatch(redirected_headers, { + 'sec-fetch-storage-access': ['inactive'], + 'origin': ['null'], + 'cookie': undefined + }); +}, "Sec-Fetch-Storage-Access is not 'active' after cross-origin same-site redirection."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + await grantStorageAccessForEmbedSite(t, cross_site); + + // Create a redirect destination that is cross-site to the + // initial request. + const redirect_url = makeURL(key, https_origin, retry_path, + [['redirected', '']]); + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin], + ['once-active-redirect-location', + redirect_url]])); + + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, { + 'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], + 'cookie': undefined + }); + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); + // Retrieve the headers for the post-retry redirect request. + const redirected_headers = await sendRetrieveRequest(redirectedKey(key)); + // These values will be empty because the frame is now same origin with + // the top level. + assertHeaderValuesMatch(redirected_headers, { + 'sec-fetch-storage-access': undefined, + 'origin': ['null'], + 'cookie': undefined + }); +}, "Sec-Fetch-Storage-Access loses value on a cross-site redirection."); + +promise_test(async (t) => { + const key = '{{uuid()}}'; + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(cross_site); + addCommonCleanupCallback(t); + await grantStorageAccessForEmbedSite(t, cross_site); + + // Create a redirect destination that is cross-origin same-site to the + // initial request. + const redirect_url = makeURL(key, https_origin, retry_path, [['redirected', '']]); + // Send a request that instructs the server to respond with both retry and + // response headers. + await sendReadableHeaderRequest(makeURL(key, cross_site, retry_path, + [['retry-allowed-origin', + https_origin], + ['redirect-location', + redirect_url]])); + // No redirect should have occurred, so a retrieval request for the + // redirect request should fail. + const redirected_headers = await sendRetrieveRequest(redirectedKey(key)); + assert_equals(redirected_headers, undefined); + // Confirm the normal retry behavior. + const headers = await sendRetrieveRequest(key); + assertHeaderValuesMatch(headers, {'sec-fetch-storage-access': ['inactive'], + 'origin': [https_origin], + 'cookie': undefined}); + const retried_headers = await sendRetrieveRequest(retriedKey(key)); + assertHeaderValuesMatch(retried_headers, { + 'sec-fetch-storage-access': ['active'], + 'origin': [https_origin], + 'cookie': ['cookie=unpartitioned'] + }); +}, "Activate-Storage-Access retry is handled before any redirects are followed."); \ No newline at end of file