Add CookieSettingOverride to allow ABA embeds to send cookies using CORS
For now, this functionality is gated behind a base::Feature that is disabled by default. This CL does *not* interact with SameSite semantics, and still maintains that only SameSite=None cookies are allowed in ABA contexts. This exception is for 3P cookie blocking only. This exception cannot be applied to cookies accessed via JS. Bug: 1513690 Change-Id: Id5964224403b7eb9aab69cebe69095530da5baa5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5147868 Reviewed-by: Caitlin Fischer <caitlinfischer@google.com> Commit-Queue: Dylan Cutler <dylancutler@google.com> Reviewed-by: Chris Fredrickson <cfredric@chromium.org> Cr-Commit-Position: refs/heads/main@{#1243468}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
67592416cf
commit
f365e8df5b
components/content_settings/core/common
content/browser/network
net
services/network
third_party/blink/web_tests
VirtualTestSuites
external
wpt
storage-access-api
virtual
saa-top-level-site-cors-exception
tools/metrics/histograms/metadata
@@ -26,6 +26,20 @@
|
|||||||
|
|
||||||
namespace content_settings {
|
namespace content_settings {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsAllowedByCORS(const net::CookieSettingOverrides& overrides,
|
||||||
|
const GURL& request_url,
|
||||||
|
const GURL& first_party_url) {
|
||||||
|
return overrides.Has(
|
||||||
|
net::CookieSettingOverride::kCrossSiteCredentialedWithCORS) &&
|
||||||
|
base::FeatureList::IsEnabled(
|
||||||
|
net::features::kThirdPartyCookieTopLevelSiteCorsException) &&
|
||||||
|
net::SchemefulSite(request_url) == net::SchemefulSite(first_party_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
bool CookieSettingsBase::storage_access_api_grants_unpartitioned_storage_ =
|
bool CookieSettingsBase::storage_access_api_grants_unpartitioned_storage_ =
|
||||||
false;
|
false;
|
||||||
|
|
||||||
@@ -365,6 +379,14 @@ CookieSettingsBase::GetCookieSettingInternal(
|
|||||||
ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT);
|
ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (block_third && IsAllowedByCORS(overrides, request_url, first_party_url)) {
|
||||||
|
block_third = false;
|
||||||
|
third_party_cookie_allow_mechanism =
|
||||||
|
ThirdPartyCookieAllowMechanism::kAllowByCORSException;
|
||||||
|
FireStorageAccessHistogram(
|
||||||
|
net::cookie_util::StorageAccessResult::ACCESS_ALLOWED_CORS_EXCEPTION);
|
||||||
|
}
|
||||||
|
|
||||||
if (block_third) {
|
if (block_third) {
|
||||||
bool has_storage_access_opt_in =
|
bool has_storage_access_opt_in =
|
||||||
ShouldConsiderStorageAccessGrants(overrides);
|
ShouldConsiderStorageAccessGrants(overrides);
|
||||||
|
@@ -98,7 +98,8 @@ class CookieSettingsBase {
|
|||||||
kAllowBy3PCDHeuristics = 5,
|
kAllowBy3PCDHeuristics = 5,
|
||||||
kAllowByStorageAccess = 6,
|
kAllowByStorageAccess = 6,
|
||||||
kAllowByTopLevelStorageAccess = 7,
|
kAllowByTopLevelStorageAccess = 7,
|
||||||
kMaxValue = kAllowByTopLevelStorageAccess,
|
kAllowByCORSException = 8,
|
||||||
|
kMaxValue = kAllowByCORSException,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CookieSettingWithMetadata {
|
class CookieSettingWithMetadata {
|
||||||
|
@@ -575,8 +575,12 @@ class ThirdPartyCookiesBlockedHttpCookieBrowserTest
|
|||||||
public:
|
public:
|
||||||
ThirdPartyCookiesBlockedHttpCookieBrowserTest()
|
ThirdPartyCookiesBlockedHttpCookieBrowserTest()
|
||||||
: https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
|
: https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
|
||||||
feature_list_.InitAndEnableFeature(
|
feature_list_.InitWithFeatures(
|
||||||
net::features::kForceThirdPartyCookieBlocking);
|
{
|
||||||
|
net::features::kForceThirdPartyCookieBlocking,
|
||||||
|
net::features::kThirdPartyCookieTopLevelSiteCorsException,
|
||||||
|
},
|
||||||
|
{});
|
||||||
}
|
}
|
||||||
|
|
||||||
~ThirdPartyCookiesBlockedHttpCookieBrowserTest() override = default;
|
~ThirdPartyCookiesBlockedHttpCookieBrowserTest() override = default;
|
||||||
@@ -615,19 +619,21 @@ class ThirdPartyCookiesBlockedHttpCookieBrowserTest
|
|||||||
return EvalJs(frame, JsReplace(script, url)).ExtractString();
|
return EvalJs(frame, JsReplace(script, url)).ExtractString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FetchWithCredentials(RenderFrameHost* frame, const GURL& url) {
|
EvalJsResult Fetch(RenderFrameHost* frame,
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& mode,
|
||||||
|
const std::string& credentials) {
|
||||||
constexpr char script[] = R"JS(
|
constexpr char script[] = R"JS(
|
||||||
fetch($1, { credentials : 'include' }
|
fetch($1, {mode: $2, credentials: $3}).then(result => result.text());
|
||||||
).then((result) => result.text());
|
|
||||||
)JS";
|
)JS";
|
||||||
return EvalJs(frame, JsReplace(script, url)).ExtractString();
|
return EvalJs(frame, JsReplace(script, url, mode, credentials));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CookieStoreEmpty(RenderFrameHost* frame) {
|
bool CookieStoreEmpty(RenderFrameHost* frame) {
|
||||||
constexpr char script[] = R"JS(
|
constexpr char script[] = R"JS(
|
||||||
(async () => {
|
(async () => {
|
||||||
let cookies = await cookieStore.getAll();
|
let cookies = await cookieStore.getAll();
|
||||||
return cookies.length == 0 ? true : false;
|
return cookies.length == 0;
|
||||||
})();
|
})();
|
||||||
)JS";
|
)JS";
|
||||||
return EvalJs(frame, script).ExtractBool();
|
return EvalJs(frame, script).ExtractBool();
|
||||||
@@ -832,10 +838,51 @@ IN_PROC_BROWSER_TEST_F(
|
|||||||
// check if cookies are present on the request.
|
// check if cookies are present on the request.
|
||||||
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
|
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
|
||||||
|
|
||||||
EXPECT_TRUE(FetchWithCredentials(
|
EXPECT_THAT(Fetch(web_contents()->GetPrimaryMainFrame(),
|
||||||
web_contents()->GetPrimaryMainFrame(),
|
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
|
||||||
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath))
|
"cors", "include")
|
||||||
.empty());
|
.ExtractString(),
|
||||||
|
net::CookieStringIs(IsEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
|
||||||
|
TopLevelSiteCorsException) {
|
||||||
|
// Set and confirm SameSite=None cookie on Site A.
|
||||||
|
ASSERT_TRUE(SetCookie(
|
||||||
|
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
|
||||||
|
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
|
||||||
|
|
||||||
|
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
|
||||||
|
|
||||||
|
// Embed an iframe containing A in B.
|
||||||
|
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
|
||||||
|
web_contents(), https_server(), base::StrCat({kHostA, "(%s)"}),
|
||||||
|
{0}, EchoCookiesUrl(kHostB)),
|
||||||
|
"None");
|
||||||
|
|
||||||
|
// Test that a subresource request from B to A can use cookies if it is
|
||||||
|
// in CORS mode and includes credentials.
|
||||||
|
EXPECT_EQ(Fetch(ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
|
||||||
|
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
|
||||||
|
"cors", "include")
|
||||||
|
.ExtractString(),
|
||||||
|
base::StrCat({kSameSiteNoneCookieName, "=1"}));
|
||||||
|
|
||||||
|
// Test that a subresource request from B to A cannot use cookies if it is
|
||||||
|
// in CORS mode and omits credentials.
|
||||||
|
EXPECT_THAT(Fetch(ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
|
||||||
|
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
|
||||||
|
"cors", "omit")
|
||||||
|
.ExtractString(),
|
||||||
|
net::CookieStringIs(IsEmpty()));
|
||||||
|
|
||||||
|
// Test that a subresource request from B to A cannot use cookies if it is
|
||||||
|
// in no-cors mode.
|
||||||
|
EXPECT_THAT(Fetch(ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
|
||||||
|
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
|
||||||
|
"no-cors", "include")
|
||||||
|
.ExtractString(),
|
||||||
|
net::CookieStringIs(IsEmpty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(/* no label */,
|
INSTANTIATE_TEST_SUITE_P(/* no label */,
|
||||||
|
@@ -465,6 +465,10 @@ BASE_FEATURE(kForceThirdPartyCookieBlocking,
|
|||||||
"ForceThirdPartyCookieBlockingEnabled",
|
"ForceThirdPartyCookieBlockingEnabled",
|
||||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||||
|
|
||||||
|
BASE_FEATURE(kThirdPartyCookieTopLevelSiteCorsException,
|
||||||
|
"ThirdPartyCookieTopLevelSiteCorsException",
|
||||||
|
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||||
|
|
||||||
BASE_FEATURE(kEnableEarlyHintsOnHttp11,
|
BASE_FEATURE(kEnableEarlyHintsOnHttp11,
|
||||||
"EnableEarlyHintsOnHttp11",
|
"EnableEarlyHintsOnHttp11",
|
||||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||||
|
@@ -467,6 +467,11 @@ NET_EXPORT BASE_DECLARE_FEATURE(kTimeLimitedInsecureCookies);
|
|||||||
// Enables enabling third-party cookie blocking from the command line.
|
// Enables enabling third-party cookie blocking from the command line.
|
||||||
NET_EXPORT BASE_DECLARE_FEATURE(kForceThirdPartyCookieBlocking);
|
NET_EXPORT BASE_DECLARE_FEATURE(kForceThirdPartyCookieBlocking);
|
||||||
|
|
||||||
|
// Enables an exception for third-party cookie blocking when the request is
|
||||||
|
// same-site with the top-level document, opted into CORS, but embedded in a
|
||||||
|
// cross-site context.
|
||||||
|
NET_EXPORT BASE_DECLARE_FEATURE(kThirdPartyCookieTopLevelSiteCorsException);
|
||||||
|
|
||||||
// Enables Early Hints on HTTP/1.1.
|
// Enables Early Hints on HTTP/1.1.
|
||||||
NET_EXPORT BASE_DECLARE_FEATURE(kEnableEarlyHintsOnHttp11);
|
NET_EXPORT BASE_DECLARE_FEATURE(kEnableEarlyHintsOnHttp11);
|
||||||
|
|
||||||
|
@@ -29,8 +29,13 @@ enum class CookieSettingOverride {
|
|||||||
// backs 3PC accesses granted via 3PC deprecation trial.
|
// backs 3PC accesses granted via 3PC deprecation trial.
|
||||||
kSkipTPCDSupport = 3,
|
kSkipTPCDSupport = 3,
|
||||||
kSkipTPCDMetadataGrant = 4,
|
kSkipTPCDMetadataGrant = 4,
|
||||||
|
// Corresponds to checks that may grant 3PCs when a request opts into
|
||||||
|
// credentials and CORS protection.
|
||||||
|
// One example are subresource requests that are same-site with the top-level
|
||||||
|
// site but originate from a cross-site embed.
|
||||||
|
kCrossSiteCredentialedWithCORS = 5,
|
||||||
|
|
||||||
kMaxValue = kSkipTPCDMetadataGrant,
|
kMaxValue = kCrossSiteCredentialedWithCORS,
|
||||||
};
|
};
|
||||||
|
|
||||||
using CookieSettingOverrides = base::EnumSet<CookieSettingOverride,
|
using CookieSettingOverrides = base::EnumSet<CookieSettingOverride,
|
||||||
|
@@ -49,7 +49,8 @@ enum class StorageAccessResult {
|
|||||||
ACCESS_ALLOWED_3PCD = 5,
|
ACCESS_ALLOWED_3PCD = 5,
|
||||||
ACCESS_ALLOWED_3PCD_METADATA_GRANT = 6,
|
ACCESS_ALLOWED_3PCD_METADATA_GRANT = 6,
|
||||||
ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT = 7,
|
ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT = 7,
|
||||||
kMaxValue = ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT,
|
ACCESS_ALLOWED_CORS_EXCEPTION = 8,
|
||||||
|
kMaxValue = ACCESS_ALLOWED_CORS_EXCEPTION,
|
||||||
};
|
};
|
||||||
// This enum must match the numbering for BreakageIndicatorType in
|
// This enum must match the numbering for BreakageIndicatorType in
|
||||||
// histograms/enums.xml. Do not reorder or remove items, only add new items
|
// histograms/enums.xml. Do not reorder or remove items, only add new items
|
||||||
|
@@ -739,6 +739,12 @@ URLLoader::URLLoader(
|
|||||||
url_request_->cookie_setting_overrides().Put(
|
url_request_->cookie_setting_overrides().Put(
|
||||||
net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible);
|
net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible);
|
||||||
}
|
}
|
||||||
|
if (network::cors::IsCorsEnabledRequestMode(request_mode_) &&
|
||||||
|
url_request_->site_for_cookies().IsNull() &&
|
||||||
|
url_request_->allow_credentials()) {
|
||||||
|
url_request_->cookie_setting_overrides().Put(
|
||||||
|
net::CookieSettingOverride::kCrossSiteCredentialedWithCORS);
|
||||||
|
}
|
||||||
|
|
||||||
AddAdsHeuristicCookieSettingOverrides(
|
AddAdsHeuristicCookieSettingOverrides(
|
||||||
request.is_ad_tagged, url_request_->cookie_setting_overrides());
|
request.is_ad_tagged, url_request_->cookie_setting_overrides());
|
||||||
|
10
third_party/blink/web_tests/VirtualTestSuites
vendored
10
third_party/blink/web_tests/VirtualTestSuites
vendored
@@ -2449,6 +2449,16 @@
|
|||||||
"expires": "Jul 1, 2024",
|
"expires": "Jul 1, 2024",
|
||||||
"owners": ["arichiv@chromium.org"]
|
"owners": ["arichiv@chromium.org"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"prefix": "saa-top-level-site-cors-exception",
|
||||||
|
"platforms": ["Linux", "Mac", "Win"],
|
||||||
|
"bases": [
|
||||||
|
"external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js"
|
||||||
|
],
|
||||||
|
"args": ["--enable-features=ThirdPartyCookieTopLevelSiteCorsException"],
|
||||||
|
"expires": "Jul 1, 2024",
|
||||||
|
"owners": ["dylancutler@google.com"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"prefix": "permission-element",
|
"prefix": "permission-element",
|
||||||
"platforms": ["Linux", "Mac", "Win"],
|
"platforms": ["Linux", "Mac", "Win"],
|
||||||
|
@@ -264,6 +264,14 @@ function FetchFromFrame(frame, url) {
|
|||||||
{ command: "cors fetch", url }, frame.contentWindow);
|
{ command: "cors fetch", url }, frame.contentWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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`;
|
||||||
|
return PostMessageAndAwaitReply(
|
||||||
|
{ command: "no-cors fetch", url }, frame.contentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
// Tries to set storage access policy, ignoring any errors.
|
// Tries to set storage access policy, ignoring any errors.
|
||||||
//
|
//
|
||||||
// Note: to discourage the writing of tests that assume unpartitioned cookie
|
// Note: to discourage the writing of tests that assume unpartitioned cookie
|
||||||
@@ -295,4 +303,4 @@ function MessageWorker(frame, message = {}) {
|
|||||||
function ReadCookiesFromWebSocketConnection(frame, origin) {
|
function ReadCookiesFromWebSocketConnection(frame, origin) {
|
||||||
return PostMessageAndAwaitReply(
|
return PostMessageAndAwaitReply(
|
||||||
{ command: "get_cookie_via_websocket", origin}, frame.contentWindow);
|
{ command: "get_cookie_via_websocket", origin}, frame.contentWindow);
|
||||||
}
|
}
|
||||||
|
@@ -75,6 +75,8 @@
|
|||||||
assert_true(cookieStringHasCookie("foo", "bar", await FetchSubresourceCookiesFromFrame(crossSiteFrame, wwwAlt)),"crossSiteFrame making same-origin subresource request can access cookies.");
|
assert_true(cookieStringHasCookie("foo", "bar", await FetchSubresourceCookiesFromFrame(crossSiteFrame, wwwAlt)),"crossSiteFrame making same-origin subresource request can access cookies.");
|
||||||
|
|
||||||
assert_false(cookieStringHasCookie("foo", "bar", await FetchSubresourceCookiesFromFrame(crossOriginFrame, wwwAlt)), "crossOriginFrame making cross-site subresource request to sibling iframe's host should not include cookies.");
|
assert_false(cookieStringHasCookie("foo", "bar", await FetchSubresourceCookiesFromFrame(crossOriginFrame, wwwAlt)), "crossOriginFrame making cross-site subresource request to sibling iframe's host should not include cookies.");
|
||||||
|
|
||||||
|
assert_false(cookieStringHasCookie("foo", "bar", await NoCorsSubresourceCookiesFromFrame(crossOriginFrame, www)), "crossSiteFrame making no-cors cross-site subresource request to sibling iframe's host should not include cookies.");
|
||||||
assert_false(cookieStringHasCookie("cookie", "monster", await FetchSubresourceCookiesFromFrame(crossSiteFrame, www)),"crossSiteFrame making cross-site subresource request to sibling iframe's host should not include cookies.");
|
assert_false(cookieStringHasCookie("cookie", "monster", await FetchSubresourceCookiesFromFrame(crossSiteFrame, www)),"crossSiteFrame making cross-site subresource request to sibling iframe's host should not include cookies.");
|
||||||
|
|
||||||
}, "Cross-site sibling iframes should not be able to take advantage of the existing permission grant requested by others.");
|
}, "Cross-site sibling iframes should not be able to take advantage of the existing permission grant requested by others.");
|
||||||
|
3
third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js
vendored
3
third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js
vendored
@@ -75,6 +75,9 @@ window.addEventListener("message", async (event) => {
|
|||||||
case "cors fetch":
|
case "cors fetch":
|
||||||
reply(await fetch(event.data.url, {mode: 'cors', credentials: 'include'}).then((resp) => resp.text()));
|
reply(await fetch(event.data.url, {mode: 'cors', credentials: 'include'}).then((resp) => resp.text()));
|
||||||
break;
|
break;
|
||||||
|
case "no-cors fetch":
|
||||||
|
reply(await fetch(event.data.url, {mode: 'no-cors', credentials: 'include'}).then((resp) => resp.text()));
|
||||||
|
break;
|
||||||
case "start_dedicated_worker":
|
case "start_dedicated_worker":
|
||||||
worker = new Worker("embedded_worker.js");
|
worker = new Worker("embedded_worker.js");
|
||||||
reply(undefined);
|
reply(undefined);
|
||||||
|
4
third_party/blink/web_tests/virtual/saa-top-level-site-cors-exception/README.md
vendored
Normal file
4
third_party/blink/web_tests/virtual/saa-top-level-site-cors-exception/README.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
This directory verifies behavior of the Storage Access API when we grant an
|
||||||
|
exception to third-party cookie blocking to requests that are to the same
|
||||||
|
site as the top-level domain, even if they have a cross-site ancestor.
|
||||||
|
`--enable-features=ThirdPartyCookieTopLevelSiteCorsException`
|
5
third_party/blink/web_tests/virtual/saa-top-level-site-cors-exception/external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window-expected.txt
vendored
Normal file
5
third_party/blink/web_tests/virtual/saa-top-level-site-cors-exception/external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window-expected.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
This is a testharness.js-based test.
|
||||||
|
[FAIL] Cross-site sibling iframes should not be able to take advantage of the existing permission grant requested by others.
|
||||||
|
assert_false: crossSiteFrame making cross-site subresource request to sibling iframe's host should not include cookies. expected false got true
|
||||||
|
Harness: the test ran to completion.
|
||||||
|
|
@@ -305,6 +305,7 @@ chromium-metrics-reviews@google.com.
|
|||||||
<int value="5" label="Allow by 3PCD heuristics"/>
|
<int value="5" label="Allow by 3PCD heuristics"/>
|
||||||
<int value="6" label="Allow by Storage access API"/>
|
<int value="6" label="Allow by Storage access API"/>
|
||||||
<int value="7" label="Allow by top-level Storage access API"/>
|
<int value="7" label="Allow by top-level Storage access API"/>
|
||||||
|
<int value="8" label="Allow by opting into CORS protections"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
</enums>
|
</enums>
|
||||||
|
@@ -301,6 +301,7 @@ chromium-metrics-reviews@google.com.
|
|||||||
<int value="6"
|
<int value="6"
|
||||||
label="Storage access allowed by 3PCD metadata grants content settings"/>
|
label="Storage access allowed by 3PCD metadata grants content settings"/>
|
||||||
<int value="7" label="Temporary storage access allowed by 3PCD heuristics"/>
|
<int value="7" label="Temporary storage access allowed by 3PCD heuristics"/>
|
||||||
|
<int value="8" label="Storage access allowed due to CORS opt in"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="StorageBucketDurabilityParameter">
|
<enum name="StorageBucketDurabilityParameter">
|
||||||
|
Reference in New Issue
Block a user