blob: 8a68fcf314ffb34ce4838662b446688e5e59bcc5 [file] [log] [blame]
Dylan Cutler27307332021-08-02 21:00:411// Copyright 2021 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Peter Vargaec193052021-12-01 10:25:055#include <string>
6
Dylan Cutler27307332021-08-02 21:00:417#include "net/cookies/cookie_partition_key.h"
Dylan Cutler39fa227e2021-08-10 22:40:048#include "base/test/scoped_feature_list.h"
9#include "net/base/features.h"
Dylan Cutler27307332021-08-02 21:00:4110#include "net/cookies/cookie_constants.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace net {
14
Dylan Cutler39fa227e2021-08-10 22:40:0415class CookiePartitionKeyTest : public testing::TestWithParam<bool> {
16 protected:
17 // testing::Test
18 void SetUp() override {
19 if (PartitionedCookiesEnabled())
20 scoped_feature_list_.InitAndEnableFeature(features::kPartitionedCookies);
21 testing::TestWithParam<bool>::SetUp();
22 }
23
24 bool PartitionedCookiesEnabled() { return GetParam(); }
25
26 private:
27 base::test::ScopedFeatureList scoped_feature_list_;
28};
29
30INSTANTIATE_TEST_SUITE_P(/* no label */,
31 CookiePartitionKeyTest,
32 testing::Bool());
33
34TEST_P(CookiePartitionKeyTest, Serialization) {
shivanigithub7aefb232021-11-18 19:26:5935 base::UnguessableToken nonce = base::UnguessableToken::Create();
Dylan Cutler27307332021-08-02 21:00:4136 struct {
37 absl::optional<CookiePartitionKey> input;
38 bool expected_ret;
39 std::string expected_output;
40 } cases[] = {
41 // No partition key
42 {absl::nullopt, true, kEmptyCookiePartitionKey},
43 // Partition key present
Dylan Cutler6ac1c67a82022-03-31 11:36:1644 {CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")),
Dylan Cutler27307332021-08-02 21:00:4145 true, "https://toplevelsite.com"},
46 // Local file URL
Dylan Cutler6ac1c67a82022-03-31 11:36:1647 {CookiePartitionKey::FromURLForTesting(GURL("file:///path/to/file.txt")),
Dylan Cutler27307332021-08-02 21:00:4148 true, "file://"},
49 // File URL with host
Dylan Cutler6ac1c67a82022-03-31 11:36:1650 {CookiePartitionKey::FromURLForTesting(
51 GURL("file://toplevelsite.com/path/to/file.pdf")),
Dylan Cutler27307332021-08-02 21:00:4152 true, "file://toplevelsite.com"},
53 // Opaque origin
Dylan Cutler6ac1c67a82022-03-31 11:36:1654 {CookiePartitionKey::FromURLForTesting(GURL()), false, ""},
shivanigithub7aefb232021-11-18 19:26:5955 // With nonce
56 {CookiePartitionKey::FromNetworkIsolationKey(NetworkIsolationKey(
57 SchemefulSite(GURL("https://toplevelsite.com")),
58 SchemefulSite(GURL("https://cookiesite.com")), &nonce)),
59 false, ""},
Dylan Cutler27307332021-08-02 21:00:4160 // Invalid partition key
61 {absl::make_optional(
62 CookiePartitionKey::FromURLForTesting(GURL("abc123foobar!!"))),
63 false, ""},
64 };
65
66 for (const auto& tc : cases) {
67 std::string got;
Dylan Cutlerc68e593e2021-09-15 22:07:2768 if (PartitionedCookiesEnabled()) {
69 EXPECT_EQ(tc.expected_ret, CookiePartitionKey::Serialize(tc.input, got));
70 EXPECT_EQ(tc.expected_output, got);
71 } else {
72 // Serialize should only return true for unpartitioned cookies if the
73 // feature is disabled.
74 EXPECT_NE(tc.input.has_value(),
75 CookiePartitionKey::Serialize(tc.input, got));
76 }
Dylan Cutler27307332021-08-02 21:00:4177 }
78}
79
Dylan Cutler39fa227e2021-08-10 22:40:0480TEST_P(CookiePartitionKeyTest, Deserialization) {
Dylan Cutler27307332021-08-02 21:00:4181 struct {
82 std::string input;
83 bool expected_ret;
84 absl::optional<CookiePartitionKey> expected_output;
85 } cases[] = {
86 {kEmptyCookiePartitionKey, true, absl::nullopt},
87 {"https://toplevelsite.com", true,
Dylan Cutler6ac1c67a82022-03-31 11:36:1688 CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"))},
Dylan Cutler27307332021-08-02 21:00:4189 {"abc123foobar!!", false, absl::nullopt},
90 };
91
92 for (const auto& tc : cases) {
93 absl::optional<CookiePartitionKey> got;
Dylan Cutlerc68e593e2021-09-15 22:07:2794 if (PartitionedCookiesEnabled()) {
95 EXPECT_EQ(tc.expected_ret,
96 CookiePartitionKey::Deserialize(tc.input, got));
97 if (tc.expected_output.has_value()) {
98 EXPECT_TRUE(got.has_value());
99 EXPECT_EQ(tc.expected_output.value(), got.value());
100 } else {
101 EXPECT_FALSE(got.has_value());
102 }
Dylan Cutler27307332021-08-02 21:00:41103 } else {
Dylan Cutlerc68e593e2021-09-15 22:07:27104 // Deserialize should only return true for unpartitioned cookies if the
105 // feature is disabled.
106 EXPECT_EQ(tc.input == kEmptyCookiePartitionKey,
107 CookiePartitionKey::Deserialize(tc.input, got));
Dylan Cutler27307332021-08-02 21:00:41108 }
109 }
110}
111
Dylan Cutler39fa227e2021-08-10 22:40:04112TEST_P(CookiePartitionKeyTest, FromNetworkIsolationKey) {
Dylan Cutlerc20782d2021-11-19 18:36:03113 const SchemefulSite kTopLevelSite =
shivanigithub7aefb232021-11-18 19:26:59114 SchemefulSite(GURL("https://toplevelsite.com"));
Dylan Cutler4ab423e2022-03-30 21:11:29115 const SchemefulSite kCookieSite =
116 SchemefulSite(GURL("https://cookiesite.com"));
117 const SchemefulSite kFirstPartySetOwnerSite =
118 SchemefulSite(GURL("https://setowner.com"));
Dylan Cutlerc20782d2021-11-19 18:36:03119 const base::UnguessableToken kNonce = base::UnguessableToken::Create();
120
Dylan Cutler4ab423e2022-03-30 21:11:29121 struct TestCase {
122 const std::string desc;
123 const NetworkIsolationKey network_isolation_key;
124 bool use_first_party_sets;
125 bool allow_nonced_partition_keys;
126 const absl::optional<CookiePartitionKey> expected;
127 } test_cases[] = {
128 {
129 "Empty",
130 NetworkIsolationKey(),
131 /*use_first_party_sets=*/false,
132 /*allow_nonced_partition_keys=*/false,
133 absl::nullopt,
134 },
135 {
136 "WithTopLevelSite",
137 NetworkIsolationKey(kTopLevelSite, kCookieSite),
138 /*use_first_party_sets=*/false,
139 /*allow_nonced_partition_keys=*/false,
140 CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL()),
141 },
142 {
143 "WithFirstPartySetOwner",
144 NetworkIsolationKey(kTopLevelSite, kCookieSite),
145 /*use_first_party_sets=*/true,
146 /*allow_nonced_partition_keys=*/false,
147 CookiePartitionKey::FromURLForTesting(
148 kFirstPartySetOwnerSite.GetURL()),
149 },
150 {
151 "WithNonce",
152 NetworkIsolationKey(kTopLevelSite, kCookieSite, &kNonce),
153 /*use_first_party_sets=*/false,
154 /*allow_nonced_partition_keys=*/false,
155 CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL(), kNonce),
156 },
157 {
158 "FirstPartySetWithNonce",
159 NetworkIsolationKey(kTopLevelSite, kCookieSite, &kNonce),
160 /*use_first_party_sets=*/true,
161 /*allow_nonced_partition_keys=*/false,
162 CookiePartitionKey::FromURLForTesting(
163 kFirstPartySetOwnerSite.GetURL(), kNonce),
164 },
165 {
166 "NoncedAllowed_KeyWithoutNonce",
167 NetworkIsolationKey(kTopLevelSite, kCookieSite),
168 /*use_first_party_sets=*/false,
169 /*allow_nonced_partition_keys=*/true,
170 CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL()),
171 },
172 {
173 "NoncedAllowed_KeyWithoutNonce",
174 NetworkIsolationKey(kTopLevelSite, kCookieSite, &kNonce),
175 /*use_first_party_sets=*/false,
176 /*allow_nonced_partition_keys=*/true,
177 CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL(), kNonce),
178 },
179 };
shivanigithub7aefb232021-11-18 19:26:59180
Dylan Cutler4ab423e2022-03-30 21:11:29181 for (const auto& test_case : test_cases) {
182 SCOPED_TRACE(test_case.desc);
shivanigithub7aefb232021-11-18 19:26:59183
Dylan Cutler4ab423e2022-03-30 21:11:29184 base::test::ScopedFeatureList feature_list;
185 std::vector<base::Feature> enabled_features;
186 std::vector<base::Feature> disabled_features;
187 if (PartitionedCookiesEnabled()) {
188 enabled_features.push_back(features::kPartitionedCookies);
189 } else {
190 disabled_features.push_back(features::kPartitionedCookies);
Dylan Cutler69a51c92021-12-08 16:32:01191 }
Dylan Cutler4ab423e2022-03-30 21:11:29192 if (test_case.allow_nonced_partition_keys) {
193 enabled_features.push_back(features::kNoncedPartitionedCookies);
194 } else {
195 disabled_features.push_back(features::kNoncedPartitionedCookies);
196 }
197 feature_list.InitWithFeatures(enabled_features, disabled_features);
Dylan Cutler69a51c92021-12-08 16:32:01198
Dylan Cutler69a51c92021-12-08 16:32:01199 absl::optional<CookiePartitionKey> got =
200 CookiePartitionKey::FromNetworkIsolationKey(
Dylan Cutler4ab423e2022-03-30 21:11:29201 test_case.network_isolation_key, test_case.use_first_party_sets
202 ? &kFirstPartySetOwnerSite
203 : nullptr);
204
205 if (got)
Dylan Cutler69a51c92021-12-08 16:32:01206 EXPECT_FALSE(got->from_script());
Dylan Cutler4ab423e2022-03-30 21:11:29207
208 if (PartitionedCookiesEnabled()) {
209 EXPECT_EQ(test_case.expected, got);
210 } else if (test_case.allow_nonced_partition_keys) {
211 EXPECT_EQ(test_case.network_isolation_key.GetNonce().has_value(),
212 got.has_value());
213 if (got)
214 EXPECT_EQ(test_case.expected, got);
215 } else {
216 EXPECT_FALSE(got);
Dylan Cutler69a51c92021-12-08 16:32:01217 }
218 }
219}
220
Dylan Cutlerab0b5732021-09-17 00:28:34221TEST_P(CookiePartitionKeyTest, FromWire) {
Dylan Cutlerc20782d2021-11-19 18:36:03222 struct TestCase {
223 const GURL url;
224 const absl::optional<base::UnguessableToken> nonce;
225 } test_cases[] = {
226 {GURL("https://foo.com"), absl::nullopt},
227 {GURL(), absl::nullopt},
228 {GURL("https://foo.com"),
229 absl::make_optional(base::UnguessableToken::Create())},
230 };
shivanigithub7aefb232021-11-18 19:26:59231
Dylan Cutlerc20782d2021-11-19 18:36:03232 for (const auto& test_case : test_cases) {
233 auto want =
234 CookiePartitionKey::FromURLForTesting(test_case.url, test_case.nonce);
235 auto got = CookiePartitionKey::FromWire(want.site(), want.nonce());
236 EXPECT_EQ(want, got);
237 EXPECT_FALSE(got.from_script());
238 }
Dylan Cutler4a461f1b2021-11-03 01:08:36239}
240
241TEST_P(CookiePartitionKeyTest, FromScript) {
242 auto key = CookiePartitionKey::FromScript();
243 EXPECT_TRUE(key);
244 EXPECT_TRUE(key->from_script());
245 EXPECT_TRUE(key->site().opaque());
Dylan Cutlerab0b5732021-09-17 00:28:34246}
247
Dylan Cutler46cb8a92021-11-17 23:29:56248TEST_P(CookiePartitionKeyTest, IsSerializeable) {
249 EXPECT_FALSE(CookiePartitionKey::FromURLForTesting(GURL()).IsSerializeable());
250 EXPECT_EQ(PartitionedCookiesEnabled(), CookiePartitionKey::FromURLForTesting(
251 GURL("https://www.example.com"))
252 .IsSerializeable());
253}
254
Dylan Cutlerc20782d2021-11-19 18:36:03255TEST_P(CookiePartitionKeyTest, Equality_WithNonce) {
shivanigithub7aefb232021-11-18 19:26:59256 SchemefulSite top_level_site =
257 SchemefulSite(GURL("https://toplevelsite.com"));
258 SchemefulSite frame_site = SchemefulSite(GURL("https://cookiesite.com"));
259 base::UnguessableToken nonce1 = base::UnguessableToken::Create();
260 base::UnguessableToken nonce2 = base::UnguessableToken::Create();
261 EXPECT_NE(nonce1, nonce2);
262 auto key1 = CookiePartitionKey::FromNetworkIsolationKey(
263 NetworkIsolationKey(top_level_site, frame_site, &nonce1));
264 bool partitioned_cookies_enabled = PartitionedCookiesEnabled();
265 EXPECT_EQ(partitioned_cookies_enabled, key1.has_value());
266 if (!partitioned_cookies_enabled)
267 return;
268
269 auto key2 = CookiePartitionKey::FromNetworkIsolationKey(
270 NetworkIsolationKey(top_level_site, frame_site, &nonce2));
271 EXPECT_TRUE(key1.has_value() && key2.has_value());
272 EXPECT_NE(key1, key2);
273
274 auto key3 = CookiePartitionKey::FromNetworkIsolationKey(
275 NetworkIsolationKey(top_level_site, frame_site, &nonce1));
276 EXPECT_EQ(key1, key3);
Dylan Cutlerff413b22022-03-25 19:29:19277
278 auto unnonced_key = CookiePartitionKey::FromNetworkIsolationKey(
279 NetworkIsolationKey(top_level_site, frame_site));
280 EXPECT_NE(key1, unnonced_key);
shivanigithub7aefb232021-11-18 19:26:59281}
282
Dylan Cutler27307332021-08-02 21:00:41283} // namespace net