0

Remove support for double-keyed NAKs

* Remove `NAK::IsCrossSiteFlagSchemeEnabled` (always true).
 * Remove `NAK::IsDoubleKeySchemeEnabled` (always false).
 * Remove leftover declaration of `NAK::IsFrameSiteEnabled`.
 * Remove all test cases for double-keyed NAKs.
 * Remove the kEnableCrossSiteFlagNetworkAnonymizationKey feature.

Bug: 1407287
Change-Id: I0c47f419fc0b07cc15af2462dfa7bc2861c05070
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4244523
Auto-Submit: Dustin Mitchell <djmitche@chromium.org>
Commit-Queue: Dustin Mitchell <djmitche@chromium.org>
Reviewed-by: Brianna Goldstein <brgoldstein@google.com>
Reviewed-by: Alex Ilin <alexilin@chromium.org>
Reviewed-by: Matt Menke <mmenke@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1111226}
This commit is contained in:
Dustin J. Mitchell
2023-02-28 22:50:40 +00:00
committed by Chromium LUCI CQ
parent 3bf767a8ec
commit c9d5d88cfe
19 changed files with 189 additions and 687 deletions

@@ -1307,9 +1307,8 @@ IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
EXPECT_EQ(2u, connection_tracker()->GetAcceptedSocketCount()); EXPECT_EQ(2u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(2u, connection_tracker()->GetReadSocketCount()); EXPECT_EQ(2u, connection_tracker()->GetReadSocketCount());
} else { } else {
// Otherwise, the preconnected socket is used, so counts remain unchanged // Otherwise, the preconnected socket cannot be used.
// since the last check. EXPECT_EQ(3u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(2u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(2u, connection_tracker()->GetReadSocketCount()); EXPECT_EQ(2u, connection_tracker()->GetReadSocketCount());
} }

@@ -189,8 +189,6 @@ class DomainReliabilityUploaderTest : public testing::Test {
uploader_( uploader_(
DomainReliabilityUploader::Create(&time_, DomainReliabilityUploader::Create(&time_,
url_request_context_.get())) { url_request_context_.get())) {
scoped_feature_list_.InitAndEnableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
expected_isolation_info_ = net::IsolationInfo::CreateTransient(); expected_isolation_info_ = net::IsolationInfo::CreateTransient();
auto interceptor = auto interceptor =
@@ -216,7 +214,6 @@ class DomainReliabilityUploaderTest : public testing::Test {
} }
private: private:
base::test::ScopedFeatureList scoped_feature_list_;
base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment task_environment_{
base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; base::test::SingleThreadTaskEnvironment::MainThreadType::IO};

@@ -113,10 +113,6 @@ BASE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey,
"PartitionNelAndReportingByNetworkIsolationKey", "PartitionNelAndReportingByNetworkIsolationKey",
base::FEATURE_DISABLED_BY_DEFAULT); base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kEnableCrossSiteFlagNetworkAnonymizationKey,
"EnableCrossSiteFlagNetworkAnonymizationKey",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kTLS13KeyUpdate, BASE_FEATURE(kTLS13KeyUpdate,
"TLS13KeyUpdate", "TLS13KeyUpdate",
base::FEATURE_DISABLED_BY_DEFAULT); base::FEATURE_DISABLED_BY_DEFAULT);

@@ -148,15 +148,6 @@ NET_EXPORT BASE_DECLARE_FEATURE(kPartitionSSLSessionsByNetworkIsolationKey);
// testing. // testing.
NET_EXPORT BASE_DECLARE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey); NET_EXPORT BASE_DECLARE_FEATURE(kPartitionNelAndReportingByNetworkIsolationKey);
// Creates a <double key + is_cross_site> NetworkAnonymizationKey which is used
// to partition the network state. This double key will have the following
// properties: `top_frame_site` -> the schemeful site of the top level page.
// `frame_site ` -> nullopt
// `is_cross_site` -> true if the `top_frame_site` is cross site when compared
// to the frame site. The frame site will not be stored in this key so the value
// of is_cross_site will be computed at key construction.
NET_EXPORT BASE_DECLARE_FEATURE(kEnableCrossSiteFlagNetworkAnonymizationKey);
// Enables sending TLS 1.3 Key Update messages on TLS 1.3 connections in order // Enables sending TLS 1.3 Key Update messages on TLS 1.3 connections in order
// to ensure that this corner of the spec is exercised. This is currently // to ensure that this corner of the spec is exercised. This is currently
// disabled by default because we discovered incompatibilities with some // disabled by default because we discovered incompatibilities with some

@@ -176,8 +176,7 @@ IsolationInfo IsolationInfo::DoNotUseCreatePartialFromNak(
network_anonymization_key.GetTopFrameSite()->site_as_origin_; network_anonymization_key.GetTopFrameSite()->site_as_origin_;
absl::optional<url::Origin> frame_origin; absl::optional<url::Origin> frame_origin;
if (NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled() && if (network_anonymization_key.GetIsCrossSite().value()) {
network_anonymization_key.GetIsCrossSite().value()) {
// If we know that the origin is cross site to the top level site, create an // If we know that the origin is cross site to the top level site, create an
// empty origin to use as the frame origin for the isolation info. This // empty origin to use as the frame origin for the isolation info. This
// should be cross site with the top level origin. // should be cross site with the top level origin.

@@ -7,7 +7,6 @@
#include <iostream> #include <iostream>
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/test/gtest_util.h" #include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "isolation_info.h" #include "isolation_info.h"
#include "net/base/features.h" #include "net/base/features.h"
@@ -23,47 +22,10 @@
namespace net { namespace net {
// `IsolationInfoEnabledFeatureFlagsTestingParam ` allows enabling and disabling
// the feature flags that control the key schemes for NetworkAnonymizationKey.
// This allows us to test the possible combinations of flags that will be
// allowed for experimentation.
//
// Presently, only one flag is used, but future experiments will add more.
struct IsolationInfoEnabledFeatureFlagsTestingParam {
const bool enableDoubleKeyAndCrossSiteBitNetworkAnonymizationKey;
};
const IsolationInfoEnabledFeatureFlagsTestingParam kFlagsParam[] = {
// 0. Double-keying is enabled for NetworkAnonymizationKey.
{/*enableDoubleKeyAndCrossSiteBitNetworkAnonymizationKey=*/false},
// 1. Double-keying + cross-site-bit is enabled for NetworkAnonymizationKey.
{/*enableDoubleKeyAndCrossSiteBitNetworkAnonymizationKey=*/true}};
namespace { namespace {
class IsolationInfoTest : public testing::Test, class IsolationInfoTest : public testing::Test {
public testing::WithParamInterface<
IsolationInfoEnabledFeatureFlagsTestingParam> {
public: public:
IsolationInfoTest() {
std::vector<base::test::FeatureRef> enabled_features = {};
std::vector<base::test::FeatureRef> disabled_features = {};
if (IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled()) {
enabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
} else {
disabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
static bool IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled() {
return GetParam().enableDoubleKeyAndCrossSiteBitNetworkAnonymizationKey;
}
const url::Origin kOrigin1 = url::Origin::Create(GURL("https://a.foo.test")); const url::Origin kOrigin1 = url::Origin::Create(GURL("https://a.foo.test"));
const url::Origin kSite1 = url::Origin::Create(GURL("https://foo.test")); const url::Origin kSite1 = url::Origin::Create(GURL("https://foo.test"));
const url::Origin kOrigin2 = url::Origin::Create(GURL("https://b.bar.test")); const url::Origin kOrigin2 = url::Origin::Create(GURL("https://b.bar.test"));
@@ -87,16 +49,8 @@ class IsolationInfoTest : public testing::Test,
const base::UnguessableToken kNonce1 = base::UnguessableToken::Create(); const base::UnguessableToken kNonce1 = base::UnguessableToken::Create();
const base::UnguessableToken kNonce2 = base::UnguessableToken::Create(); const base::UnguessableToken kNonce2 = base::UnguessableToken::Create();
private:
base::test::ScopedFeatureList scoped_feature_list_;
}; };
INSTANTIATE_TEST_SUITE_P(All,
IsolationInfoTest,
/*IsolationInfoEnabledFeatureFlagsTestingParam */
testing::ValuesIn(kFlagsParam));
void DuplicateAndCompare(const IsolationInfo& isolation_info) { void DuplicateAndCompare(const IsolationInfo& isolation_info) {
absl::optional<IsolationInfo> duplicate_isolation_info = absl::optional<IsolationInfo> duplicate_isolation_info =
IsolationInfo::CreateIfConsistent( IsolationInfo::CreateIfConsistent(
@@ -112,11 +66,11 @@ void DuplicateAndCompare(const IsolationInfo& isolation_info) {
EXPECT_TRUE(isolation_info.IsEqualForTesting(*duplicate_isolation_info)); EXPECT_TRUE(isolation_info.IsEqualForTesting(*duplicate_isolation_info));
} }
TEST_P(IsolationInfoTest, IsFrameSiteEnabled) { TEST_F(IsolationInfoTest, IsFrameSiteEnabled) {
EXPECT_TRUE(IsolationInfo::IsFrameSiteEnabled()); EXPECT_TRUE(IsolationInfo::IsFrameSiteEnabled());
} }
TEST_P(IsolationInfoTest, DebugString) { TEST_F(IsolationInfoTest, DebugString) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin2, IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin2,
SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1); SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1);
@@ -138,7 +92,7 @@ TEST_P(IsolationInfoTest, DebugString) {
EXPECT_EQ(isolation_info.DebugString(), base::StrCat(parts)); EXPECT_EQ(isolation_info.DebugString(), base::StrCat(parts));
} }
TEST_P(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfo) { TEST_F(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfo) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin2, IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin2,
SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1); SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1);
@@ -162,24 +116,18 @@ TEST_P(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfo) {
kNonce1); kNonce1);
EXPECT_EQ(isolation_info.nonce().value(), kNonce1); EXPECT_EQ(isolation_info.nonce().value(), kNonce1);
if (!IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled()) { // Triple-keyed IsolationInfo + double-keyed + cross site bit
// Triple-keyed IsolationInfo + double-keyed NetworkAnonymizationKey case. // NetworkAnonymizationKey case.
EXPECT_EQ(isolation_info.frame_origin(), kOrigin2); EXPECT_EQ(isolation_info.frame_origin(), kOrigin2);
} else { EXPECT_EQ(isolation_info.network_anonymization_key().GetIsCrossSite(), true);
// Triple-keyed IsolationInfo + double-keyed + cross site bit EXPECT_EQ(
// NetworkAnonymizationKey case. same_site_isolation_info.network_anonymization_key().GetIsCrossSite(),
EXPECT_EQ(isolation_info.frame_origin(), kOrigin2); false);
EXPECT_EQ(isolation_info.network_anonymization_key().GetIsCrossSite(),
true);
EXPECT_EQ(
same_site_isolation_info.network_anonymization_key().GetIsCrossSite(),
false);
}
} }
// A 2.5-keyed NAK created with two identical opaque origins should be // A 2.5-keyed NAK created with two identical opaque origins should be
// same-site. // same-site.
TEST_P(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfoOpaque) { TEST_F(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfoOpaque) {
url::Origin opaque; url::Origin opaque;
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, opaque, opaque, IsolationInfo::RequestType::kMainFrame, opaque, opaque,
@@ -188,22 +136,16 @@ TEST_P(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfoOpaque) {
isolation_info.CreateNetworkAnonymizationKeyForIsolationInfo( isolation_info.CreateNetworkAnonymizationKeyForIsolationInfo(
opaque, opaque, &kNonce1); opaque, opaque, &kNonce1);
if (IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled()) { EXPECT_FALSE(nak.GetIsCrossSite().value());
EXPECT_FALSE(nak.GetIsCrossSite().value());
} else {
EXPECT_DCHECK_DEATH(nak.GetIsCrossSite());
}
url::Origin opaque2; url::Origin opaque2;
nak = isolation_info.CreateNetworkAnonymizationKeyForIsolationInfo( nak = isolation_info.CreateNetworkAnonymizationKeyForIsolationInfo(
opaque, opaque2, &kNonce1); opaque, opaque2, &kNonce1);
if (IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled()) { EXPECT_TRUE(nak.GetIsCrossSite().value());
EXPECT_TRUE(nak.GetIsCrossSite().value());
}
} }
TEST_P(IsolationInfoTest, RequestTypeMainFrame) { TEST_F(IsolationInfoTest, RequestTypeMainFrame) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1, IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1,
SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty); SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty);
@@ -241,7 +183,7 @@ TEST_P(IsolationInfoTest, RequestTypeMainFrame) {
EXPECT_FALSE(redirected_isolation_info.nonce().has_value()); EXPECT_FALSE(redirected_isolation_info.nonce().has_value());
} }
TEST_P(IsolationInfoTest, RequestTypeSubFrame) { TEST_F(IsolationInfoTest, RequestTypeSubFrame) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2, IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2,
SiteForCookies::FromOrigin(kOrigin1), kPartyContext1); SiteForCookies::FromOrigin(kOrigin1), kPartyContext1);
@@ -279,7 +221,7 @@ TEST_P(IsolationInfoTest, RequestTypeSubFrame) {
EXPECT_FALSE(redirected_isolation_info.nonce().has_value()); EXPECT_FALSE(redirected_isolation_info.nonce().has_value());
} }
TEST_P(IsolationInfoTest, RequestTypeMainFrameWithNonce) { TEST_F(IsolationInfoTest, RequestTypeMainFrameWithNonce) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1, IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1,
SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1); SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1);
@@ -316,7 +258,7 @@ TEST_P(IsolationInfoTest, RequestTypeMainFrameWithNonce) {
EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value()); EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value());
} }
TEST_P(IsolationInfoTest, RequestTypeSubFrameWithNonce) { TEST_F(IsolationInfoTest, RequestTypeSubFrameWithNonce) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2, IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2,
SiteForCookies::FromOrigin(kOrigin1), kPartyContext1, &kNonce1); SiteForCookies::FromOrigin(kOrigin1), kPartyContext1, &kNonce1);
@@ -353,7 +295,7 @@ TEST_P(IsolationInfoTest, RequestTypeSubFrameWithNonce) {
EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value()); EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value());
} }
TEST_P(IsolationInfoTest, RequestTypeOther) { TEST_F(IsolationInfoTest, RequestTypeOther) {
IsolationInfo isolation_info; IsolationInfo isolation_info;
EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type()); EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type());
EXPECT_FALSE(isolation_info.top_frame_origin()); EXPECT_FALSE(isolation_info.top_frame_origin());
@@ -370,7 +312,7 @@ TEST_P(IsolationInfoTest, RequestTypeOther) {
EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info)); EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info));
} }
TEST_P(IsolationInfoTest, RequestTypeOtherWithSiteForCookies) { TEST_F(IsolationInfoTest, RequestTypeOtherWithSiteForCookies) {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin1, kOrigin1, IsolationInfo::RequestType::kOther, kOrigin1, kOrigin1,
SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty); SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty);
@@ -395,7 +337,7 @@ TEST_P(IsolationInfoTest, RequestTypeOtherWithSiteForCookies) {
// Test case of a subresource for cross-site subframe (which has an empty // Test case of a subresource for cross-site subframe (which has an empty
// site-for-cookies). // site-for-cookies).
TEST_P(IsolationInfoTest, RequestTypeOtherWithEmptySiteForCookies) { TEST_F(IsolationInfoTest, RequestTypeOtherWithEmptySiteForCookies) {
IsolationInfo isolation_info = IsolationInfo isolation_info =
IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin1, IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin1,
kOrigin2, SiteForCookies(), kPartyContext2); kOrigin2, SiteForCookies(), kPartyContext2);
@@ -417,7 +359,7 @@ TEST_P(IsolationInfoTest, RequestTypeOtherWithEmptySiteForCookies) {
EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info)); EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info));
} }
TEST_P(IsolationInfoTest, CreateTransient) { TEST_F(IsolationInfoTest, CreateTransient) {
IsolationInfo isolation_info = IsolationInfo::CreateTransient(); IsolationInfo isolation_info = IsolationInfo::CreateTransient();
EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type()); EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type());
EXPECT_TRUE(isolation_info.top_frame_origin()->opaque()); EXPECT_TRUE(isolation_info.top_frame_origin()->opaque());
@@ -435,7 +377,7 @@ TEST_P(IsolationInfoTest, CreateTransient) {
EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info)); EXPECT_TRUE(isolation_info.IsEqualForTesting(redirected_isolation_info));
} }
TEST_P(IsolationInfoTest, CreateForInternalRequest) { TEST_F(IsolationInfoTest, CreateForInternalRequest) {
IsolationInfo isolation_info = IsolationInfo isolation_info =
IsolationInfo::CreateForInternalRequest(kOrigin1); IsolationInfo::CreateForInternalRequest(kOrigin1);
EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type()); EXPECT_EQ(IsolationInfo::RequestType::kOther, isolation_info.request_type());
@@ -459,7 +401,7 @@ TEST_P(IsolationInfoTest, CreateForInternalRequest) {
// Test that in the UpdateNothing case, the SiteForCookies does not have to // Test that in the UpdateNothing case, the SiteForCookies does not have to
// match the frame origin, unlike in the HTTP/HTTPS case. // match the frame origin, unlike in the HTTP/HTTPS case.
TEST_P(IsolationInfoTest, CustomSchemeRequestTypeOther) { TEST_F(IsolationInfoTest, CustomSchemeRequestTypeOther) {
// Have to register the scheme, or url::Origin::Create() will return an // Have to register the scheme, or url::Origin::Create() will return an
// opaque origin. // opaque origin.
url::ScopedSchemeRegistryForTests scoped_registry; url::ScopedSchemeRegistryForTests scoped_registry;
@@ -491,7 +433,7 @@ TEST_P(IsolationInfoTest, CustomSchemeRequestTypeOther) {
// Success cases are covered by other tests, so only need a separate test to // Success cases are covered by other tests, so only need a separate test to
// cover the failure cases. // cover the failure cases.
TEST_P(IsolationInfoTest, CreateIfConsistentFails) { TEST_F(IsolationInfoTest, CreateIfConsistentFails) {
// Main frames with inconsistent SiteForCookies. // Main frames with inconsistent SiteForCookies.
EXPECT_FALSE(IsolationInfo::CreateIfConsistent( EXPECT_FALSE(IsolationInfo::CreateIfConsistent(
IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1, IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1,
@@ -553,7 +495,7 @@ TEST_P(IsolationInfoTest, CreateIfConsistentFails) {
SiteForCookies(), absl::nullopt /* party_context */, &kNonce1)); SiteForCookies(), absl::nullopt /* party_context */, &kNonce1));
} }
TEST_P(IsolationInfoTest, CreateForRedirectPartyContext) { TEST_F(IsolationInfoTest, CreateForRedirectPartyContext) {
// RequestTypeMainFrame, PartyContext is empty // RequestTypeMainFrame, PartyContext is empty
{ {
IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo isolation_info = IsolationInfo::Create(
@@ -592,7 +534,7 @@ TEST_P(IsolationInfoTest, CreateForRedirectPartyContext) {
} }
} }
TEST_P(IsolationInfoTest, Serialization) { TEST_F(IsolationInfoTest, Serialization) {
EXPECT_FALSE(IsolationInfo::Deserialize("")); EXPECT_FALSE(IsolationInfo::Deserialize(""));
EXPECT_FALSE(IsolationInfo::Deserialize("garbage")); EXPECT_FALSE(IsolationInfo::Deserialize("garbage"));

@@ -20,27 +20,25 @@ NetworkAnonymizationKey::NetworkAnonymizationKey(
const absl::optional<bool> is_cross_site, const absl::optional<bool> is_cross_site,
const absl::optional<base::UnguessableToken> nonce) const absl::optional<base::UnguessableToken> nonce)
: top_frame_site_(top_frame_site), : top_frame_site_(top_frame_site),
is_cross_site_(IsCrossSiteFlagSchemeEnabled() ? is_cross_site is_cross_site_(is_cross_site),
: absl::nullopt),
nonce_(nonce) { nonce_(nonce) {
DCHECK(top_frame_site_.has_value()); DCHECK(top_frame_site_.has_value());
// If `is_cross_site` is enabled but the value is not populated, and we have // If `is_cross_site` is enabled but the value is not populated, and we have
// the information to calculate it, do calculate it. // the information to calculate it, do calculate it.
if (IsCrossSiteFlagSchemeEnabled() && !is_cross_site_.has_value() && if (!is_cross_site_.has_value() && frame_site.has_value()) {
frame_site.has_value()) {
is_cross_site_ = frame_site.value() != top_frame_site_.value(); is_cross_site_ = frame_site.value() != top_frame_site_.value();
} }
if (IsCrossSiteFlagSchemeEnabled()) {
// If `frame_site_` is populated, `is_cross_site_` must be as well. // `is_cross_site_` must be populated.
DCHECK(is_cross_site_.has_value()); // TODO(crbug.com/1407287): update constructor signature so this is not
} // optional.
DCHECK(is_cross_site_.has_value());
} }
NetworkAnonymizationKey NetworkAnonymizationKey::CreateFromNetworkIsolationKey( NetworkAnonymizationKey NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
const net::NetworkIsolationKey& network_isolation_key) { const net::NetworkIsolationKey& network_isolation_key) {
// If NIK is double-keyed, a 2.5-keyed NAK cannot be constructed from it. // If NIK is double-keyed, a 2.5-keyed NAK cannot be constructed from it.
DCHECK(NetworkIsolationKey::IsFrameSiteEnabled() || DCHECK(NetworkIsolationKey::IsFrameSiteEnabled());
IsDoubleKeySchemeEnabled());
// We cannot create a valid NetworkAnonymizationKey from a NetworkIsolationKey // We cannot create a valid NetworkAnonymizationKey from a NetworkIsolationKey
// that is not fully populated. // that is not fully populated.
@@ -48,16 +46,9 @@ NetworkAnonymizationKey NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
return NetworkAnonymizationKey(); return NetworkAnonymizationKey();
} }
// If we are unable to determine the value of `is_cross_site` from the // Determine is_cross_site based on the NIK's triple-key
// NetworkIsolationKey, we default the value to `nullopt`. Otherwise we bool nak_is_cross_site = network_isolation_key.GetTopFrameSite().value() !=
// calculate what the value will be. If the NetworkAnonymizationKey is being network_isolation_key.GetFrameSite().value();
// constructed in a scheme where the is cross site value is not used this
// value will be overridden in the constructor and set to `nullopt`.
absl::optional<bool> nak_is_cross_site = absl::nullopt;
if (NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled()) {
nak_is_cross_site = network_isolation_key.GetTopFrameSite().value() !=
network_isolation_key.GetFrameSite().value();
}
return NetworkAnonymizationKey( return NetworkAnonymizationKey(
network_isolation_key.GetTopFrameSite().value(), absl::nullopt, network_isolation_key.GetTopFrameSite().value(), absl::nullopt,
@@ -87,14 +78,12 @@ NetworkAnonymizationKey NetworkAnonymizationKey::CreateTransient() {
} }
std::string NetworkAnonymizationKey::ToDebugString() const { std::string NetworkAnonymizationKey::ToDebugString() const {
if (!IsFullyPopulated()) {
return "null";
}
std::string str = GetSiteDebugString(top_frame_site_); std::string str = GetSiteDebugString(top_frame_site_);
std::string cross_site_str = str += GetIsCrossSite().value() ? " cross_site" : " same_site";
IsCrossSiteFlagSchemeEnabled()
? (!GetIsCrossSite().has_value() ? " with empty is_cross_site value"
: GetIsCrossSite().value() ? " cross_site"
: " same_site")
: "";
str += cross_site_str;
// Currently, if the NAK has a nonce it will be marked transient. For debug // Currently, if the NAK has a nonce it will be marked transient. For debug
// purposes we will print the value but if called via // purposes we will print the value but if called via
@@ -111,8 +100,7 @@ bool NetworkAnonymizationKey::IsEmpty() const {
} }
bool NetworkAnonymizationKey::IsFullyPopulated() const { bool NetworkAnonymizationKey::IsFullyPopulated() const {
return top_frame_site_.has_value() && return top_frame_site_.has_value() && is_cross_site_.has_value();
(!IsCrossSiteFlagSchemeEnabled() || is_cross_site_.has_value());
} }
bool NetworkAnonymizationKey::IsTransient() const { bool NetworkAnonymizationKey::IsTransient() const {
@@ -123,20 +111,9 @@ bool NetworkAnonymizationKey::IsTransient() const {
} }
absl::optional<bool> NetworkAnonymizationKey::GetIsCrossSite() const { absl::optional<bool> NetworkAnonymizationKey::GetIsCrossSite() const {
DCHECK(IsCrossSiteFlagSchemeEnabled());
return is_cross_site_; return is_cross_site_;
} }
bool NetworkAnonymizationKey::IsDoubleKeySchemeEnabled() {
return !base::FeatureList::IsEnabled(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
}
bool NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled() {
return base::FeatureList::IsEnabled(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
}
bool NetworkAnonymizationKey::ToValue(base::Value* out_value) const { bool NetworkAnonymizationKey::ToValue(base::Value* out_value) const {
if (IsEmpty()) { if (IsEmpty()) {
*out_value = base::Value(base::Value::Type::LIST); *out_value = base::Value(base::Value::Type::LIST);
@@ -153,14 +130,8 @@ bool NetworkAnonymizationKey::ToValue(base::Value* out_value) const {
base::Value::List list; base::Value::List list;
list.Append(std::move(top_frame_value).value()); list.Append(std::move(top_frame_value).value());
// Append frame site for tripe key scheme or is_cross_site flag for double key const absl::optional<bool> is_cross_site = GetIsCrossSite();
// with cross site flag scheme. list.Append(is_cross_site.value());
if (IsCrossSiteFlagSchemeEnabled()) {
const absl::optional<bool> is_cross_site = GetIsCrossSite();
if (is_cross_site.has_value()) {
list.Append(is_cross_site.value());
}
}
*out_value = base::Value(std::move(list)); *out_value = base::Value(std::move(list));
return true; return true;
@@ -178,10 +149,12 @@ bool NetworkAnonymizationKey::FromValue(
return true; return true;
} }
// Check top_level_site is valid for any key scheme // Check the format.
if (list.size() < 1 || !list[0].is_string()) { if (list.size() != 2 || !list[0].is_string() || !list[1].is_bool()) {
return false; return false;
} }
// Check top_level_site is valid for any key scheme
absl::optional<SchemefulSite> top_frame_site = absl::optional<SchemefulSite> top_frame_site =
SchemefulSite::DeserializeWithNonce(list[0].GetString()); SchemefulSite::DeserializeWithNonce(list[0].GetString());
if (!top_frame_site) { if (!top_frame_site) {
@@ -191,21 +164,7 @@ bool NetworkAnonymizationKey::FromValue(
absl::optional<SchemefulSite> frame_site = absl::nullopt; absl::optional<SchemefulSite> frame_site = absl::nullopt;
absl::optional<bool> is_cross_site = absl::nullopt; absl::optional<bool> is_cross_site = absl::nullopt;
// If double key scheme is enabled `list` must be of length 1. list[0] will be is_cross_site = list[1].GetBool();
// top_frame_site.
if (IsDoubleKeySchemeEnabled()) {
if (list.size() != 1) {
return false;
}
} else /* if (IsCrossSiteFlagSchemeEnabled()) */ {
// If double key + is cross site scheme is enabled `list` must be of
// length 2. list[0] will be top_frame_site and list[1] will be
// is_cross_site.
if (list.size() != 2 || !list[1].is_bool()) {
return false;
}
is_cross_site = list[1].GetBool();
}
*network_anonymization_key = *network_anonymization_key =
NetworkAnonymizationKey(std::move(top_frame_site.value()), NetworkAnonymizationKey(std::move(top_frame_site.value()),

@@ -31,12 +31,9 @@ namespace net {
// In order to separate first and third party context from each other this field // In order to separate first and third party context from each other this field
// will always be populated. // will always be populated.
//`is_cross_site` is an expiremental boolean that will be used with the // `is_cross_site` is used with the `top_frame_site` to create a partition key
//`top_frame_site` to create a partition key that separates the // that separates the `top_frame_site`s first party partition from any
//`top_frame_site`s first party partition from any cross-site iframes. This will // cross-site iframes.
// be used only when `kEnableCrossSiteFlagNetworkAnonymizationKey` is enabled.
// When `kEnableCrossSiteFlagNetworkAnonymizationKey` is disabled,
// `is_cross_site_` will be an empty optional.
// The following show how the `is_cross_site` boolean is populated for the // The following show how the `is_cross_site` boolean is populated for the
// innermost frame in the chain. // innermost frame in the chain.
@@ -147,29 +144,6 @@ class NET_EXPORT NetworkAnonymizationKey {
return nonce_; return nonce_;
} }
// Returns true if the NetworkAnonymizationKey has a triple keyed scheme. This
// means the values of the NetworkAnonymizationKey are as follows:
// `top_frame_site` -> the schemeful site of the top level page.
// `frame_site ` -> the schemeful site of the requestor frame
// `is_cross_site` -> nullopt
static bool IsFrameSiteEnabled();
// Returns true if the NetworkAnonymizationKey has a double keyed scheme. This
// means the values of the NetworkAnonymizationKey are as follows:
// `top_frame_site` -> the schemeful site of the top level page.
// `frame_site ` -> nullopt
// `is_cross_site` -> nullopt
static bool IsDoubleKeySchemeEnabled();
// Returns true if the NetworkAnonymizationKey has a <double keyed +
// is_cross_site> scheme. This means the values of the NetworkAnonymizationKey
// are as follows:
// `top_frame_site` -> the schemeful site of the top level page.
// `frame_site ` -> nullopt
// `is_cross_site` -> a boolean indicating if the requestor frame site is
// cross site from the top level site.
static bool IsCrossSiteFlagSchemeEnabled();
// Returns a representation of |this| as a base::Value. Returns false on // Returns a representation of |this| as a base::Value. Returns false on
// failure. Succeeds if either IsEmpty() or !IsTransient(). // failure. Succeeds if either IsEmpty() or !IsTransient().
[[nodiscard]] bool ToValue(base::Value* out_value) const; [[nodiscard]] bool ToValue(base::Value* out_value) const;

@@ -18,79 +18,15 @@
namespace net { namespace net {
// `EnabledFeatureFlagsTestingParam ` allows enabling and disabling class NetworkAnonymizationKeyTest : public testing::Test {
// the feature flags that control the key schemes for NetworkAnonymizationKey.
// This allows us to test the possible combinations of flags that will be
// allowed for experimentation.
struct EnabledFeatureFlagsTestingParam {
// True = 2.5-keyed NAK, false = double-keyed NAK.
const bool enableCrossSiteFlagNetworkAnonymizationKey;
};
const EnabledFeatureFlagsTestingParam kFlagsParam[] = {
// 0. Double-keying is enabled for NetworkAnonymizationKey.
{/*enableCrossSiteFlagNetworkAnonymizationKey=*/false},
// 1. Double-keying + cross-site-bit is enabled for NetworkAnonymizationKey.
{/*enableCrossSiteFlagNetworkAnonymizationKey=*/true}};
class NetworkAnonymizationKeyTest
: public testing::Test,
public testing::WithParamInterface<EnabledFeatureFlagsTestingParam> {
public:
void SetUp() override {
std::vector<base::test::FeatureRef> enabled_features = {};
std::vector<base::test::FeatureRef> disabled_features = {};
if (IsCrossSiteFlagEnabled()) {
enabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
} else {
disabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
bool IsCrossSiteFlagEnabled() {
return GetParam().enableCrossSiteFlagNetworkAnonymizationKey;
}
protected: protected:
const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/")); const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/"));
const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/")); const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/"));
const SchemefulSite kDataSite = SchemefulSite(GURL("data:foo")); const SchemefulSite kDataSite = SchemefulSite(GURL("data:foo"));
const base::UnguessableToken kNonce = base::UnguessableToken::Create(); const base::UnguessableToken kNonce = base::UnguessableToken::Create();
private:
base::test::ScopedFeatureList scoped_feature_list_;
}; };
INSTANTIATE_TEST_SUITE_P(All, TEST_F(NetworkAnonymizationKeyTest, CreateFromNetworkIsolationKey) {
NetworkAnonymizationKeyTest,
testing::ValuesIn(kFlagsParam));
TEST_P(NetworkAnonymizationKeyTest, IsDoubleKeySchemeEnabled) {
// Double key scheme is enabled only when
// `kEnableCrossSiteFlagNetworkAnonymizationKey` is not.
if (!IsCrossSiteFlagEnabled()) {
EXPECT_TRUE(NetworkAnonymizationKey::IsDoubleKeySchemeEnabled());
} else {
EXPECT_FALSE(NetworkAnonymizationKey::IsDoubleKeySchemeEnabled());
}
}
TEST_P(NetworkAnonymizationKeyTest, IsCrossSiteFlagSchemeEnabled) {
// Double key with cross site flag scheme is enabled whenever
// `kEnableCrossSiteFlagNetworkAnonymizationKey` is enabled.
if (IsCrossSiteFlagEnabled()) {
EXPECT_TRUE(NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled());
} else {
EXPECT_FALSE(NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled());
}
}
TEST_P(NetworkAnonymizationKeyTest, CreateFromNetworkIsolationKey) {
SchemefulSite site_a = SchemefulSite(GURL("http://a.test/")); SchemefulSite site_a = SchemefulSite(GURL("http://a.test/"));
SchemefulSite site_b = SchemefulSite(GURL("http://b.test/")); SchemefulSite site_b = SchemefulSite(GURL("http://b.test/"));
SchemefulSite opaque = SchemefulSite(url::Origin()); SchemefulSite opaque = SchemefulSite(url::Origin());
@@ -102,12 +38,12 @@ TEST_P(NetworkAnonymizationKeyTest, CreateFromNetworkIsolationKey) {
&nik_nonce); &nik_nonce);
NetworkIsolationKey empty_nik; NetworkIsolationKey empty_nik;
NetworkAnonymizationKey nak_from_cross_site_nik =
NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
populated_cross_site_nik);
NetworkAnonymizationKey nak_from_same_site_nik = NetworkAnonymizationKey nak_from_same_site_nik =
NetworkAnonymizationKey::CreateFromNetworkIsolationKey( NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
populated_same_site_nik); populated_same_site_nik);
NetworkAnonymizationKey nak_from_cross_site_nik =
NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
populated_cross_site_nik);
NetworkAnonymizationKey nak_from_same_site_opaque_nik = NetworkAnonymizationKey nak_from_same_site_opaque_nik =
NetworkAnonymizationKey::CreateFromNetworkIsolationKey( NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
populated_same_site_opaque_nik); populated_same_site_opaque_nik);
@@ -118,47 +54,27 @@ TEST_P(NetworkAnonymizationKeyTest, CreateFromNetworkIsolationKey) {
// empty NAK. // empty NAK.
EXPECT_TRUE(nak_from_empty_nik.IsEmpty()); EXPECT_TRUE(nak_from_empty_nik.IsEmpty());
// Double-keyed NetworkAnonymizationKey case. // Top site should be populated correctly.
if (!IsCrossSiteFlagEnabled()) { EXPECT_EQ(nak_from_same_site_nik.GetTopFrameSite(), site_a);
// Top site should be populated correctly. EXPECT_EQ(nak_from_cross_site_nik.GetTopFrameSite(), site_a);
EXPECT_EQ(nak_from_cross_site_nik.GetTopFrameSite(), site_a); EXPECT_EQ(nak_from_same_site_opaque_nik.GetTopFrameSite(), opaque);
EXPECT_EQ(nak_from_same_site_nik.GetTopFrameSite(), site_a);
EXPECT_EQ(nak_from_same_site_opaque_nik.GetTopFrameSite(), opaque);
// Nonce should be populated correctly. // Nonce should be populated correctly.
EXPECT_EQ(nak_from_cross_site_nik.GetNonce(), nik_nonce); EXPECT_EQ(nak_from_same_site_nik.GetNonce(), nik_nonce);
EXPECT_EQ(nak_from_same_site_nik.GetNonce(), nik_nonce); EXPECT_EQ(nak_from_cross_site_nik.GetNonce(), nik_nonce);
EXPECT_EQ(nak_from_same_site_opaque_nik.GetNonce(), nik_nonce); EXPECT_EQ(nak_from_same_site_opaque_nik.GetNonce(), nik_nonce);
// Double-keyed NAKs created from different third party cross site contexts // Is cross site boolean should be populated correctly.
// should be the same. EXPECT_EQ(nak_from_same_site_nik.GetIsCrossSite(), false);
EXPECT_TRUE(nak_from_same_site_nik == nak_from_cross_site_nik); EXPECT_EQ(nak_from_cross_site_nik.GetIsCrossSite(), true);
} EXPECT_EQ(nak_from_same_site_opaque_nik.GetIsCrossSite(), false);
// Double-keyed + cross site bit NetworkAnonymizationKey case. // Double-keyed + cross site bit NAKs created from different third party
if (IsCrossSiteFlagEnabled()) { // cross site contexts should be the different.
// Top site should be populated correctly. EXPECT_FALSE(nak_from_same_site_nik == nak_from_cross_site_nik);
EXPECT_EQ(nak_from_cross_site_nik.GetTopFrameSite(), site_a);
EXPECT_EQ(nak_from_same_site_nik.GetTopFrameSite(), site_a);
EXPECT_EQ(nak_from_same_site_opaque_nik.GetTopFrameSite(), opaque);
// Nonce should be populated correctly.
EXPECT_EQ(nak_from_same_site_nik.GetNonce(), nik_nonce);
EXPECT_EQ(nak_from_cross_site_nik.GetNonce(), nik_nonce);
EXPECT_EQ(nak_from_same_site_opaque_nik.GetNonce(), nik_nonce);
// Is cross site boolean should be populated correctly.
EXPECT_EQ(nak_from_same_site_nik.GetIsCrossSite(), false);
EXPECT_EQ(nak_from_cross_site_nik.GetIsCrossSite(), true);
EXPECT_EQ(nak_from_same_site_opaque_nik.GetIsCrossSite(), false);
// Double-keyed + cross site bit NAKs created from different third party
// cross site contexts should be the different.
EXPECT_FALSE(nak_from_same_site_nik == nak_from_cross_site_nik);
}
} }
TEST_P(NetworkAnonymizationKeyTest, IsEmpty) { TEST_F(NetworkAnonymizationKeyTest, IsEmpty) {
NetworkAnonymizationKey empty_key; NetworkAnonymizationKey empty_key;
NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
@@ -169,7 +85,7 @@ TEST_P(NetworkAnonymizationKeyTest, IsEmpty) {
EXPECT_FALSE(populated_key.IsEmpty()); EXPECT_FALSE(populated_key.IsEmpty());
} }
TEST_P(NetworkAnonymizationKeyTest, CreateTransient) { TEST_F(NetworkAnonymizationKeyTest, CreateTransient) {
NetworkAnonymizationKey transient_key1 = NetworkAnonymizationKey transient_key1 =
NetworkAnonymizationKey::CreateTransient(); NetworkAnonymizationKey::CreateTransient();
NetworkAnonymizationKey transient_key2 = NetworkAnonymizationKey transient_key2 =
@@ -180,7 +96,7 @@ TEST_P(NetworkAnonymizationKeyTest, CreateTransient) {
EXPECT_FALSE(transient_key1 == transient_key2); EXPECT_FALSE(transient_key1 == transient_key2);
} }
TEST_P(NetworkAnonymizationKeyTest, IsTransient) { TEST_F(NetworkAnonymizationKeyTest, IsTransient) {
NetworkAnonymizationKey empty_key; NetworkAnonymizationKey empty_key;
NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
@@ -215,7 +131,7 @@ TEST_P(NetworkAnonymizationKeyTest, IsTransient) {
EXPECT_FALSE(populated_double_key.IsTransient()); EXPECT_FALSE(populated_double_key.IsTransient());
} }
TEST_P(NetworkAnonymizationKeyTest, IsFullyPopulated) { TEST_F(NetworkAnonymizationKeyTest, IsFullyPopulated) {
NetworkAnonymizationKey empty_key; NetworkAnonymizationKey empty_key;
NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey populated_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
@@ -234,63 +150,59 @@ TEST_P(NetworkAnonymizationKeyTest, IsFullyPopulated) {
/*nonce=*/absl::nullopt); /*nonce=*/absl::nullopt);
EXPECT_TRUE(empty_frame_site_key.IsFullyPopulated()); EXPECT_TRUE(empty_frame_site_key.IsFullyPopulated());
// is_cross_site is required when // is_cross_site is required. Since we have both the top_frame_site and
// `kEnableCrossSiteFlagNetworkAnonymizationKey` is enabled. // frame_site values the constructor should calculate and set `is_cross_site`.
// Since we have both the top_frame_site and frame_site values the constructor
// should calculate and set `is_cross_site`.
EXPECT_TRUE(empty_cross_site_flag_key.IsFullyPopulated()); EXPECT_TRUE(empty_cross_site_flag_key.IsFullyPopulated());
} }
TEST_P(NetworkAnonymizationKeyTest, IsCrossSiteFlagCalculatedInConstructor) { TEST_F(NetworkAnonymizationKeyTest, IsCrossSiteFlagCalculatedInConstructor) {
if (IsCrossSiteFlagEnabled()) { NetworkAnonymizationKey cross_site_key(/*top_frame_site=*/kTestSiteA,
NetworkAnonymizationKey cross_site_key(/*top_frame_site=*/kTestSiteA, /*frame_site=*/kTestSiteB,
/*frame_site=*/kTestSiteB, /*is_cross_site=*/true);
/*is_cross_site=*/true); NetworkAnonymizationKey equal_cross_site_key(/*top_frame_site=*/kTestSiteA,
NetworkAnonymizationKey equal_cross_site_key(/*top_frame_site=*/kTestSiteA, /*frame_site=*/kTestSiteB);
/*frame_site=*/kTestSiteB); EXPECT_EQ(cross_site_key.GetIsCrossSite().value(), true);
EXPECT_EQ(cross_site_key.GetIsCrossSite().value(), true); EXPECT_EQ(equal_cross_site_key.GetIsCrossSite().value(), true);
EXPECT_EQ(equal_cross_site_key.GetIsCrossSite().value(), true); EXPECT_EQ(cross_site_key, equal_cross_site_key);
EXPECT_EQ(cross_site_key, equal_cross_site_key);
NetworkAnonymizationKey same_site_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey same_site_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteA, /*frame_site=*/kTestSiteA,
/*is_cross_site=*/false); /*is_cross_site=*/false);
NetworkAnonymizationKey equal_same_site_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey equal_same_site_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteA); /*frame_site=*/kTestSiteA);
EXPECT_EQ(same_site_key.GetIsCrossSite().value(), false); EXPECT_EQ(same_site_key.GetIsCrossSite().value(), false);
EXPECT_EQ(equal_same_site_key.GetIsCrossSite().value(), false); EXPECT_EQ(equal_same_site_key.GetIsCrossSite().value(), false);
EXPECT_EQ(same_site_key, equal_same_site_key); EXPECT_EQ(same_site_key, equal_same_site_key);
SchemefulSite opaque = SchemefulSite(url::Origin()); SchemefulSite opaque = SchemefulSite(url::Origin());
NetworkAnonymizationKey same_opaque_site_key(/*top_frame_site=*/opaque, NetworkAnonymizationKey same_opaque_site_key(/*top_frame_site=*/opaque,
/*frame_site=*/opaque, /*frame_site=*/opaque,
/*is_cross_site=*/false); /*is_cross_site=*/false);
NetworkAnonymizationKey equal_same_opaque_site_key( NetworkAnonymizationKey equal_same_opaque_site_key(
/*top_frame_site=*/opaque, /*top_frame_site=*/opaque,
/*frame_site=*/opaque); /*frame_site=*/opaque);
EXPECT_EQ(same_opaque_site_key.GetIsCrossSite().value(), false); EXPECT_EQ(same_opaque_site_key.GetIsCrossSite().value(), false);
EXPECT_EQ(equal_same_opaque_site_key.GetIsCrossSite().value(), false); EXPECT_EQ(equal_same_opaque_site_key.GetIsCrossSite().value(), false);
EXPECT_EQ(same_opaque_site_key, equal_same_opaque_site_key); EXPECT_EQ(same_opaque_site_key, equal_same_opaque_site_key);
SchemefulSite opaque2 = SchemefulSite(url::Origin()); SchemefulSite opaque2 = SchemefulSite(url::Origin());
NetworkAnonymizationKey diff_opaque_site_key(/*top_frame_site=*/opaque, NetworkAnonymizationKey diff_opaque_site_key(/*top_frame_site=*/opaque,
/*frame_site=*/opaque2, /*frame_site=*/opaque2,
/*is_cross_site=*/true); /*is_cross_site=*/true);
NetworkAnonymizationKey equal_diff_opaque_site_key( NetworkAnonymizationKey equal_diff_opaque_site_key(
/*top_frame_site=*/opaque, /*top_frame_site=*/opaque,
/*frame_site=*/opaque2); /*frame_site=*/opaque2);
EXPECT_EQ(diff_opaque_site_key.GetIsCrossSite().value(), true); EXPECT_EQ(diff_opaque_site_key.GetIsCrossSite().value(), true);
EXPECT_EQ(equal_diff_opaque_site_key.GetIsCrossSite().value(), true); EXPECT_EQ(equal_diff_opaque_site_key.GetIsCrossSite().value(), true);
EXPECT_EQ(diff_opaque_site_key, equal_diff_opaque_site_key); EXPECT_EQ(diff_opaque_site_key, equal_diff_opaque_site_key);
NetworkAnonymizationKey double_key_cross_site(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey double_key_cross_site(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/absl::nullopt, /*frame_site=*/absl::nullopt,
true); true);
EXPECT_EQ(double_key_cross_site.GetIsCrossSite().value(), true); EXPECT_EQ(double_key_cross_site.GetIsCrossSite().value(), true);
}
} }
TEST_P(NetworkAnonymizationKeyTest, Getters) { TEST_F(NetworkAnonymizationKeyTest, Getters) {
NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
/*is_cross_site=*/true, kNonce); /*is_cross_site=*/true, kNonce);
@@ -298,41 +210,25 @@ TEST_P(NetworkAnonymizationKeyTest, Getters) {
EXPECT_EQ(key.GetTopFrameSite(), kTestSiteA); EXPECT_EQ(key.GetTopFrameSite(), kTestSiteA);
EXPECT_EQ(key.GetNonce(), kNonce); EXPECT_EQ(key.GetNonce(), kNonce);
// is_cross_site should only be true when EXPECT_TRUE(key.GetIsCrossSite().value());
// `kEnableCrossSiteFlagNetworkAnonymizationKey` is enabled.
if (IsCrossSiteFlagEnabled()) {
EXPECT_TRUE(key.GetIsCrossSite());
}
} }
TEST_P(NetworkAnonymizationKeyTest, ToDebugString) { TEST_F(NetworkAnonymizationKeyTest, ToDebugString) {
NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
/*is_cross_site=*/true, kNonce); /*is_cross_site=*/true, kNonce);
NetworkAnonymizationKey empty_key; NetworkAnonymizationKey empty_key;
if (!IsCrossSiteFlagEnabled()) { // `is_cross_site` holds the value the key is created with.
// When double key scheme is enabled, the `is_cross_site` flag is always std::string double_key_with_cross_site_flag_expected_string_value =
// forced to false. kTestSiteA.GetDebugString() + " cross_site (with nonce " +
std::string double_key_expected_string_value = kNonce.ToString() + ")";
kTestSiteA.GetDebugString() + " (with nonce " + kNonce.ToString() + ")"; EXPECT_EQ(key.ToDebugString(),
EXPECT_EQ(key.ToDebugString(), double_key_expected_string_value); double_key_with_cross_site_flag_expected_string_value);
EXPECT_EQ(empty_key.ToDebugString(), "null"); EXPECT_EQ(empty_key.ToDebugString(), "null");
} else {
// When double key + cross site flag scheme is enabled frame site is null,
// but `is_cross_site` holds the value the key is created with.
std::string double_key_with_cross_site_flag_expected_string_value =
kTestSiteA.GetDebugString() + " cross_site (with nonce " +
kNonce.ToString() + ")";
EXPECT_EQ(key.ToDebugString(),
double_key_with_cross_site_flag_expected_string_value);
// is_cross_site_ will be stored as nullopt when it's not populated even if
// IsCrossSiteFlagEnabled is enabled.
EXPECT_EQ(empty_key.ToDebugString(), "null with empty is_cross_site value");
}
} }
TEST_P(NetworkAnonymizationKeyTest, Equality) { TEST_F(NetworkAnonymizationKeyTest, Equality) {
NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
/*is_cross_site=*/false, kNonce); /*is_cross_site=*/false, kNonce);
@@ -347,17 +243,10 @@ TEST_P(NetworkAnonymizationKeyTest, Equality) {
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
/*is_cross_site=*/true, kNonce); /*is_cross_site=*/true, kNonce);
// The `is_cross_site` flag only changes the NAK when // The `is_cross_site` flag changes the NAK.
// `kEnableCrossSiteFlagNetworkAnonymizationKey` is enabled. EXPECT_FALSE(key == key_cross_site);
if (IsCrossSiteFlagEnabled()) { EXPECT_TRUE(key != key_cross_site);
EXPECT_FALSE(key == key_cross_site); EXPECT_TRUE(key < key_cross_site);
EXPECT_TRUE(key != key_cross_site);
EXPECT_TRUE(key < key_cross_site);
} else {
EXPECT_TRUE(key == key_cross_site);
EXPECT_FALSE(key != key_cross_site);
EXPECT_FALSE(key < key_cross_site);
}
NetworkAnonymizationKey key_no_nonce(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey key_no_nonce(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
@@ -401,7 +290,7 @@ TEST_P(NetworkAnonymizationKeyTest, Equality) {
EXPECT_TRUE(empty_key < key); EXPECT_TRUE(empty_key < key);
} }
TEST_P(NetworkAnonymizationKeyTest, ValueRoundTripCrossSite) { TEST_F(NetworkAnonymizationKeyTest, ValueRoundTripCrossSite) {
const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk")); const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk"));
NetworkAnonymizationKey original_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey original_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, /*frame_site=*/kTestSiteB,
@@ -415,7 +304,7 @@ TEST_P(NetworkAnonymizationKeyTest, ValueRoundTripCrossSite) {
EXPECT_EQ(original_key, from_value_key); EXPECT_EQ(original_key, from_value_key);
} }
TEST_P(NetworkAnonymizationKeyTest, ValueRoundTripSameSite) { TEST_F(NetworkAnonymizationKeyTest, ValueRoundTripSameSite) {
const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk")); const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk"));
NetworkAnonymizationKey original_key(/*top_frame_site=*/kTestSiteA, NetworkAnonymizationKey original_key(/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteA, /*frame_site=*/kTestSiteA,
@@ -429,7 +318,7 @@ TEST_P(NetworkAnonymizationKeyTest, ValueRoundTripSameSite) {
EXPECT_EQ(original_key, from_value_key); EXPECT_EQ(original_key, from_value_key);
} }
TEST_P(NetworkAnonymizationKeyTest, TransientValueRoundTrip) { TEST_F(NetworkAnonymizationKeyTest, TransientValueRoundTrip) {
const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk")); const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk"));
NetworkAnonymizationKey original_key = NetworkAnonymizationKey original_key =
NetworkAnonymizationKey::CreateTransient(); NetworkAnonymizationKey::CreateTransient();
@@ -437,7 +326,7 @@ TEST_P(NetworkAnonymizationKeyTest, TransientValueRoundTrip) {
ASSERT_FALSE(original_key.ToValue(&value)); ASSERT_FALSE(original_key.ToValue(&value));
} }
TEST_P(NetworkAnonymizationKeyTest, EmptyValueRoundTrip) { TEST_F(NetworkAnonymizationKeyTest, EmptyValueRoundTrip) {
const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk")); const SchemefulSite kOpaqueSite = SchemefulSite(GURL("data:text/html,junk"));
NetworkAnonymizationKey original_key; NetworkAnonymizationKey original_key;
base::Value value; base::Value value;
@@ -457,20 +346,27 @@ TEST(NetworkAnonymizationKeyFeatureShiftTest,
const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/")); const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/"));
NetworkAnonymizationKey expected_failure_nak = NetworkAnonymizationKey(); NetworkAnonymizationKey expected_failure_nak = NetworkAnonymizationKey();
// Turn double keying on (or disable 2.5-keying) // Create a cross site double key + cross site flag NetworkAnonymizationKey.
scoped_feature_list_.Reset(); NetworkAnonymizationKey original_cross_site_double_key(
scoped_feature_list_.InitAndDisableFeature( /*top_frame_site=*/kTestSiteA,
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey); /*frame_site=*/kTestSiteB, false);
base::Value cross_site_double_key_value;
ASSERT_TRUE(
original_cross_site_double_key.ToValue(&cross_site_double_key_value));
// Create a double keyed NetworkAnonymizationKey. // Check that deserializing a double keyed NetworkAnonymizationKey (a
NetworkAnonymizationKey original_double_key(/*top_frame_site=*/kTestSiteA); // one-element list) fails, using the serialized site from
// Serialize key to value while double keying is enabled. // `cross_site_double_key_value` to build it.
base::Value double_key_value; base::Value serialized_site =
ASSERT_TRUE(original_double_key.ToValue(&double_key_value)); cross_site_double_key_value.GetList()[0].Clone();
base::Value::List double_key_list;
double_key_list.Append(serialized_site.Clone());
base::Value double_key_value = base::Value(std::move(double_key_list));
EXPECT_FALSE(NetworkAnonymizationKey::FromValue(double_key_value,
&expected_failure_nak));
// Check that deserializing a triple keyed value fails. Such values // Check that deserializing a triple keyed value (a 2-element list containing
// cannot be constructed, but may still exist on-disk. // two sites) fails.
base::Value serialized_site = double_key_value.GetList()[0].Clone();
base::Value::List triple_key_list; base::Value::List triple_key_list;
triple_key_list.Append(serialized_site.Clone()); triple_key_list.Append(serialized_site.Clone());
triple_key_list.Append(std::move(serialized_site)); triple_key_list.Append(std::move(serialized_site));
@@ -478,49 +374,12 @@ TEST(NetworkAnonymizationKeyFeatureShiftTest,
EXPECT_FALSE(NetworkAnonymizationKey::FromValue(triple_key_value, EXPECT_FALSE(NetworkAnonymizationKey::FromValue(triple_key_value,
&expected_failure_nak)); &expected_failure_nak));
// Convert it back to a double keyed NetworkAnonymizationKey. // Convert the successful value back to a NAK and verify.
NetworkAnonymizationKey from_value_double_key = NetworkAnonymizationKey();
EXPECT_TRUE(NetworkAnonymizationKey::FromValue(double_key_value,
&from_value_double_key));
EXPECT_EQ(original_double_key, from_value_double_key);
// Turn double keying + cross site flag on.
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndEnableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
// Check that deserializing the triple keyed value fails.
EXPECT_FALSE(NetworkAnonymizationKey::FromValue(triple_key_value,
&expected_failure_nak));
// Check that deserializing the double keyed value fails.
EXPECT_FALSE(NetworkAnonymizationKey::FromValue(double_key_value,
&expected_failure_nak));
// Create a cross site double key + cross site flag NetworkAnonymizationKey.
NetworkAnonymizationKey original_cross_site_double_key(
/*top_frame_site=*/kTestSiteA,
/*frame_site=*/kTestSiteB, false);
// Serialize key to value while double key + cross site flag is enabled.
base::Value cross_site_double_key_value;
ASSERT_TRUE(
original_cross_site_double_key.ToValue(&cross_site_double_key_value));
// Convert it back to a double keyed NetworkAnonymizationKey.
NetworkAnonymizationKey from_value_cross_site_double_key = NetworkAnonymizationKey from_value_cross_site_double_key =
NetworkAnonymizationKey(); NetworkAnonymizationKey();
EXPECT_TRUE(NetworkAnonymizationKey::FromValue( EXPECT_TRUE(NetworkAnonymizationKey::FromValue(
cross_site_double_key_value, &from_value_cross_site_double_key)); cross_site_double_key_value, &from_value_cross_site_double_key));
EXPECT_EQ(original_cross_site_double_key, from_value_cross_site_double_key); EXPECT_EQ(original_cross_site_double_key, from_value_cross_site_double_key);
// Turn double keying on (or disable 2.5-keying)
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndDisableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
// Check that deserializing the cross site double keyed value fails.
EXPECT_FALSE(NetworkAnonymizationKey::FromValue(cross_site_double_key_value,
&expected_failure_nak));
} }
} // namespace net } // namespace net

@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "net/http/http_request_info.h" #include "net/http/http_request_info.h"
#include "base/test/scoped_feature_list.h"
#include "net/base/features.h" #include "net/base/features.h"
#include "net/base/network_anonymization_key.h" #include "net/base/network_anonymization_key.h"
#include "net/base/network_isolation_key.h" #include "net/base/network_isolation_key.h"
@@ -12,30 +11,20 @@
namespace net { namespace net {
TEST(HTTPRequestInfoTest, IsConsistent) { TEST(HTTPRequestInfoTest, IsConsistent) {
// TODO(brgoldstein): refactor this test with new testing config enum when
// you update NetworkAnonymizationKey tests and IsolationInfo tests.
const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/")); const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/"));
const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/")); const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/"));
net::HttpRequestInfo triple_nik_double_nak_request_info; net::HttpRequestInfo with_anon_nak;
triple_nik_double_nak_request_info.network_isolation_key = with_anon_nak.network_isolation_key =
NetworkIsolationKey(kTestSiteA, kTestSiteB); NetworkIsolationKey(kTestSiteA, kTestSiteB);
EXPECT_FALSE(with_anon_nak.IsConsistent());
// Triple key NIK and double key NAK. net::HttpRequestInfo cross_site;
base::test::ScopedFeatureList scoped_feature_list_; cross_site.network_isolation_key =
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndDisableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
EXPECT_FALSE(triple_nik_double_nak_request_info.IsConsistent());
net::HttpRequestInfo triple_nik_double_xsite_bit_nak_request_info;
triple_nik_double_xsite_bit_nak_request_info.network_isolation_key =
NetworkIsolationKey(kTestSiteA, kTestSiteB); NetworkIsolationKey(kTestSiteA, kTestSiteB);
triple_nik_double_xsite_bit_nak_request_info.network_anonymization_key = cross_site.network_anonymization_key =
NetworkAnonymizationKey(kTestSiteA, kTestSiteB, true); NetworkAnonymizationKey(kTestSiteA, kTestSiteB, true);
EXPECT_TRUE(triple_nik_double_xsite_bit_nak_request_info.IsConsistent()); EXPECT_TRUE(cross_site.IsConsistent());
} }
} // namespace net } // namespace net

@@ -1151,7 +1151,7 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) {
{ {
"originPolicies": [ "originPolicies": [
{ {
"NetworkAnonymizationKey": "https://example.com", "NetworkAnonymizationKey": "https://example.com same_site",
"origin": "https://example.com", "origin": "https://example.com",
"includeSubdomains": false, "includeSubdomains": false,
"expires": "86400000", "expires": "86400000",
@@ -1160,7 +1160,7 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) {
"failureFraction": 1.0, "failureFraction": 1.0,
}, },
{ {
"NetworkAnonymizationKey": "https://example.com", "NetworkAnonymizationKey": "https://example.com same_site",
"origin": "https://invalid-types.example.com", "origin": "https://invalid-types.example.com",
"includeSubdomains": false, "includeSubdomains": false,
"expires": "86400000", "expires": "86400000",
@@ -1169,7 +1169,7 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) {
"failureFraction": 1.0, "failureFraction": 1.0,
}, },
{ {
"NetworkAnonymizationKey": "https://example.com", "NetworkAnonymizationKey": "https://example.com same_site",
"origin": "https://somewhere-else.com", "origin": "https://somewhere-else.com",
"includeSubdomains": false, "includeSubdomains": false,
"expires": "86400000", "expires": "86400000",
@@ -1178,7 +1178,7 @@ TEST_P(NetworkErrorLoggingServiceTest, StatusAsValue) {
"failureFraction": 1.0, "failureFraction": 1.0,
}, },
{ {
"NetworkAnonymizationKey": "https://somewhere-else.com", "NetworkAnonymizationKey": "https://somewhere-else.com same_site",
"origin": "https://subdomain.example.com", "origin": "https://subdomain.example.com",
"includeSubdomains": true, "includeSubdomains": true,
"expires": "86400000", "expires": "86400000",

@@ -148,7 +148,7 @@ TEST(ClientSocketPool, GroupIdToString) {
SecureDnsPolicy::kAllow) SecureDnsPolicy::kAllow)
.ToString()); .ToString());
EXPECT_EQ("https://foo <https://foo.test>", EXPECT_EQ("https://foo <https://foo.test cross_site>",
ClientSocketPool::GroupId( ClientSocketPool::GroupId(
url::SchemeHostPort(url::kHttpsScheme, "foo", 443), url::SchemeHostPort(url::kHttpsScheme, "foo", 443),
PrivacyMode::PRIVACY_MODE_DISABLED, PrivacyMode::PRIVACY_MODE_DISABLED,

@@ -1188,8 +1188,7 @@ IsolationInfo URLRequest::CreateIsolationInfoFromNetworkAnonymizationKey(
network_anonymization_key.GetTopFrameSite()->site_as_origin_; network_anonymization_key.GetTopFrameSite()->site_as_origin_;
absl::optional<url::Origin> frame_origin; absl::optional<url::Origin> frame_origin;
if (NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled() && if (network_anonymization_key.GetIsCrossSite().value()) {
network_anonymization_key.GetIsCrossSite().value()) {
// If we know that the origin is cross site to the top level site, create an // If we know that the origin is cross site to the top level site, create an
// empty origin to use as the frame origin for the isolation info. This // empty origin to use as the frame origin for the isolation info. This
// should be cross site with the top level origin. // should be cross site with the top level origin.

@@ -12883,12 +12883,7 @@ TEST_F(URLRequestTest, SetURLChain) {
} }
} }
TEST_F(URLRequestTest, TEST_F(URLRequestTest, SetIsolationInfoFromNak) {
SetIsolationInfoFromNakTripleNikDoublePlusCrossSiteBitNak) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
TestDelegate d; TestDelegate d;
SchemefulSite site_a = SchemefulSite(GURL("https://a.com/")); SchemefulSite site_a = SchemefulSite(GURL("https://a.com/"));
SchemefulSite site_b = SchemefulSite(GURL("https://b.com/")); SchemefulSite site_b = SchemefulSite(GURL("https://b.com/"));
@@ -12946,119 +12941,6 @@ TEST_F(URLRequestTest,
d.RunUntilComplete(); d.RunUntilComplete();
} }
TEST_F(URLRequestTest, SetIsolationInfoFromNakTripleNikDoubleNak) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndDisableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
TestDelegate d;
SchemefulSite site_a = SchemefulSite(GURL("https://a.com/"));
SchemefulSite site_b = SchemefulSite(GURL("https://b.com/"));
base::UnguessableToken nak_nonce = base::UnguessableToken::Create();
NetworkAnonymizationKey populated_cross_site_nak(site_a, site_b, true,
nak_nonce);
NetworkAnonymizationKey populated_same_site_nak(site_a, site_a, false,
nak_nonce);
IsolationInfo expected_isolation_info_populated_same_site_nak =
IsolationInfo::Create(IsolationInfo::RequestType::kOther,
url::Origin::Create(GURL("https://a.com/")),
url::Origin::Create(GURL("https://a.com/")),
SiteForCookies(),
/*party_context=*/absl::nullopt, &nak_nonce);
NetworkAnonymizationKey empty_nak;
GURL original_url("http://localhost");
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info_from_network_anonymization_key(
populated_cross_site_nak);
r->SetLoadFlags(LOAD_DISABLE_CACHE);
r->set_allow_credentials(false);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_EQ(r->isolation_info().network_anonymization_key(),
populated_cross_site_nak);
EXPECT_EQ(r->isolation_info().top_frame_origin(),
url::Origin::Create(GURL("https://a.com/")));
// When double key is enabled for NAK but not for NIK, the frame site of the
// IsolationInfo will be set to the top level site.
EXPECT_EQ(r->isolation_info().frame_origin(),
url::Origin::Create(GURL("https://a.com/")));
r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE);
EXPECT_EQ(r->isolation_info().network_anonymization_key(),
populated_same_site_nak);
EXPECT_TRUE(r->isolation_info().IsEqualForTesting(
expected_isolation_info_populated_same_site_nak));
r->set_isolation_info_from_network_anonymization_key(empty_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE);
EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak);
EXPECT_FALSE(r->isolation_info().top_frame_origin());
EXPECT_FALSE(r->isolation_info().frame_origin());
r->Start();
d.RunUntilComplete();
}
TEST_F(URLRequestTest,
SetIsolationInfoFromNakTripleNikDoubleWithCrossSiteFlagNak) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
TestDelegate d;
SchemefulSite site_a = SchemefulSite(GURL("https://a.com/"));
SchemefulSite site_b = SchemefulSite(GURL("https://b.com/"));
base::UnguessableToken nak_nonce = base::UnguessableToken::Create();
NetworkAnonymizationKey populated_cross_site_nak(
site_a, site_b, /*is_cross_site=*/true, nak_nonce);
NetworkAnonymizationKey populated_same_site_nak(
site_a, site_a, /*is_cross_site=*/false, nak_nonce);
NetworkAnonymizationKey empty_nak;
GURL original_url("http://localhost");
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info_from_network_anonymization_key(
populated_cross_site_nak);
r->SetLoadFlags(LOAD_DISABLE_CACHE);
r->set_allow_credentials(false);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE);
EXPECT_EQ(r->isolation_info().network_anonymization_key().ToDebugString(),
populated_cross_site_nak.ToDebugString());
EXPECT_EQ(r->isolation_info().top_frame_origin(),
url::Origin::Create(GURL("https://a.com/")));
// When double key is enabled for NAK but not for NIK, the frame site of the
// IsolationInfo will be set to the top level site.
EXPECT_TRUE(r->isolation_info().frame_origin());
r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE);
EXPECT_EQ(r->isolation_info().network_anonymization_key().ToDebugString(),
populated_same_site_nak.ToDebugString());
EXPECT_EQ(r->isolation_info().top_frame_origin(),
url::Origin::Create(GURL("https://a.com/")));
// Cross site double keyed NAKs should set a cross site dummy origin on the
// IsolationInfo.
EXPECT_TRUE(r->isolation_info().frame_origin());
r->set_isolation_info_from_network_anonymization_key(empty_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE);
EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak);
EXPECT_FALSE(r->isolation_info().top_frame_origin());
EXPECT_FALSE(r->isolation_info().frame_origin());
r->Start();
d.RunUntilComplete();
}
TEST_F(URLRequestTest, CookiePartitionKey) { TEST_F(URLRequestTest, CookiePartitionKey) {
const url::Origin kOrigin = url::Origin::Create(GURL("http://foo.test/")); const url::Origin kOrigin = url::Origin::Create(GURL("http://foo.test/"));
@@ -13172,53 +13054,14 @@ INSTANTIATE_TEST_SUITE_P(,
URLRequestMaybeAsyncFirstPartySetsTest, URLRequestMaybeAsyncFirstPartySetsTest,
testing::Bool()); testing::Bool());
namespace { class PartitionConnectionsByNetworkAnonymizationKey : public URLRequestTest {
// `EnabledFeatureFlagsTestingParam ` allows enabling and disabling
// the feature flags that control the key schemes for NetworkAnonymizationKey.
// This allows us to test the possible combinations of flags that will be
// allowed for experimentation.
//
// Presently, only one flag is used, but future experiments will add more.
struct EnabledFeatureFlagsTestingParam {
// True = 2.5-keyed NAK, false = double-keyed NAK.
const bool enable_cross_site_flag_network_anonymization_key;
};
const EnabledFeatureFlagsTestingParam kFlagsParam[] = {
// 0. Double-keying is enabled for NetworkAnonymizationKey.
{/*enable_cross_site_flag_network_anonymization_key=*/false},
// 1. Double-keying + cross-site-bit is enabled for NetworkAnonymizationKey.
{/*enable_cross_site_flag_network_anonymization_key=*/true}};
} // namespace
class PartitionConnectionsByNetworkAnonymizationKey
: public URLRequestTest,
public testing::WithParamInterface<EnabledFeatureFlagsTestingParam> {
public: public:
PartitionConnectionsByNetworkAnonymizationKey() { PartitionConnectionsByNetworkAnonymizationKey() {
std::vector<base::test::FeatureRef> enabled_features = { scoped_feature_list_.InitWithFeatures(
net::features::kPartitionConnectionsByNetworkIsolationKey, {net::features::kPartitionConnectionsByNetworkIsolationKey,
net::features::kPartitionSSLSessionsByNetworkIsolationKey}; net::features::kPartitionSSLSessionsByNetworkIsolationKey},
std::vector<base::test::FeatureRef> disabled_features = {}; {});
if (IsCrossSiteFlagEnabled()) {
enabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
} else {
disabled_features.push_back(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
} }
bool IsCrossSiteFlagEnabled() const {
return GetParam().enable_cross_site_flag_network_anonymization_key;
}
const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/")); const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/"));
const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/")); const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/"));
const SchemefulSite kTestSiteC = SchemefulSite(GURL("http://c.test/")); const SchemefulSite kTestSiteC = SchemefulSite(GURL("http://c.test/"));
@@ -13229,7 +13072,7 @@ class PartitionConnectionsByNetworkAnonymizationKey
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
}; };
TEST_P(PartitionConnectionsByNetworkAnonymizationKey, TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
DifferentTopFrameSitesNeverShareConnections) { DifferentTopFrameSitesNeverShareConnections) {
// Start server // Start server
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
@@ -13289,7 +13132,7 @@ TEST_P(PartitionConnectionsByNetworkAnonymizationKey,
} }
} }
TEST_P(PartitionConnectionsByNetworkAnonymizationKey, TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
FirstPartyIsSeparatedFromCrossSiteFrames) { FirstPartyIsSeparatedFromCrossSiteFrames) {
// Start server // Start server
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
@@ -13343,17 +13186,12 @@ TEST_P(PartitionConnectionsByNetworkAnonymizationKey,
d.RunUntilComplete(); d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk()); EXPECT_THAT(d.request_status(), IsOk());
// We should only share a connection with r1 if double key // We should not share a connection with r1.
// NetworkAnonymizationKey scheme is enabled. EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r2->ssl_info().handshake_type);
if (!IsCrossSiteFlagEnabled()) {
EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r2->ssl_info().handshake_type);
} else {
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r2->ssl_info().handshake_type);
}
} }
} }
TEST_P( TEST_F(
PartitionConnectionsByNetworkAnonymizationKey, PartitionConnectionsByNetworkAnonymizationKey,
DifferentCrossSiteFramesAreSeparatedOnlyWhenNetworkAnonymizationKeyIsTripleKeyed) { DifferentCrossSiteFramesAreSeparatedOnlyWhenNetworkAnonymizationKeyIsTripleKeyed) {
// Start server // Start server
@@ -13415,7 +13253,7 @@ TEST_P(
} }
} }
TEST_P(PartitionConnectionsByNetworkAnonymizationKey, TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
DifferentNoncesAreAlwaysSeparated) { DifferentNoncesAreAlwaysSeparated) {
// Start server // Start server
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
@@ -13479,8 +13317,4 @@ TEST_P(PartitionConnectionsByNetworkAnonymizationKey,
} }
} }
INSTANTIATE_TEST_SUITE_P(All,
PartitionConnectionsByNetworkAnonymizationKey,
testing::ValuesIn(kFlagsParam));
} // namespace net } // namespace net

@@ -23,8 +23,7 @@ bool StructTraits<network::mojom::NetworkAnonymizationKeyDataView,
// Read is_cross_site boolean flag value. // Read is_cross_site boolean flag value.
absl::optional<bool> is_cross_site = absl::nullopt; absl::optional<bool> is_cross_site = absl::nullopt;
if (net::NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled() && if (top_frame_site.has_value()) {
top_frame_site.has_value()) {
is_cross_site = data.is_cross_site(); is_cross_site = data.is_cross_site();
} }

@@ -29,9 +29,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
} }
static bool is_cross_site(const net::NetworkAnonymizationKey& input) { static bool is_cross_site(const net::NetworkAnonymizationKey& input) {
if (!net::NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled()) {
return false;
}
return input.GetIsCrossSite().value_or(false); return input.GetIsCrossSite().value_or(false);
} }

@@ -15,38 +15,10 @@
#include "url/origin.h" #include "url/origin.h"
namespace mojo { namespace mojo {
TEST(NetworkAnonymizationKeyMojomTraitsTest, SerializeAndDeserializeDoubleKey) {
// Enable double keying.
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndDisableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
base::UnguessableToken token = base::UnguessableToken::Create();
std::vector<net::NetworkAnonymizationKey> keys = {
net::NetworkAnonymizationKey(),
net::NetworkAnonymizationKey::CreateTransient(),
net::NetworkAnonymizationKey(net::SchemefulSite(GURL("http://a.test/")),
net::SchemefulSite(GURL("http://b.test/")),
&token),
net::NetworkAnonymizationKey(net::SchemefulSite(GURL("http://a.test/")))};
for (auto& original : keys) {
SCOPED_TRACE(original.ToDebugString());
net::NetworkAnonymizationKey copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
network::mojom::NetworkAnonymizationKey>(original, copied));
EXPECT_EQ(original, copied);
}
}
// TODO(crbug.com/1371667): Test is failing. // TODO(crbug.com/1371667): Test is failing.
TEST(NetworkAnonymizationKeyMojomTraitsTest, TEST(NetworkAnonymizationKeyMojomTraitsTest,
DISABLED_SerializeAndDeserializeDoubleKeyWithCrossSiteFlag) { DISABLED_SerializeAndDeserializeDoubleKeyWithCrossSiteFlag) {
// Enable double keying with cross site flag.
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kEnableCrossSiteFlagNetworkAnonymizationKey);
base::UnguessableToken token = base::UnguessableToken::Create(); base::UnguessableToken token = base::UnguessableToken::Create();
std::vector<net::NetworkAnonymizationKey> keys = { std::vector<net::NetworkAnonymizationKey> keys = {
net::NetworkAnonymizationKey(), net::NetworkAnonymizationKey(),

@@ -10,9 +10,6 @@ import "services/network/public/mojom/schemeful_site.mojom";
// Mapped to net::NetworkAnonymizationKey. // Mapped to net::NetworkAnonymizationKey.
struct NetworkAnonymizationKey { struct NetworkAnonymizationKey {
SchemefulSite? top_frame_site; SchemefulSite? top_frame_site;
// This has no effect unless
//`NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled()`
// is true.
bool is_cross_site; bool is_cross_site;
mojo_base.mojom.UnguessableToken? nonce; mojo_base.mojom.UnguessableToken? nonce;

@@ -8902,7 +8902,6 @@
{ {
"name": "enabled_triple_nik_cross_site_flag_nak_rollout", "name": "enabled_triple_nik_cross_site_flag_nak_rollout",
"enable_features": [ "enable_features": [
"EnableCrossSiteFlagNetworkAnonymizationKey",
"PartitionConnectionsByNetworkIsolationKey", "PartitionConnectionsByNetworkIsolationKey",
"PartitionDomainReliabilityByNetworkIsolationKey", "PartitionDomainReliabilityByNetworkIsolationKey",
"PartitionHttpServerPropertiesByNetworkIsolationKey", "PartitionHttpServerPropertiesByNetworkIsolationKey",