1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cookies/cookie_partition_key_collection.h"
6
7 #include "base/run_loop.h"
8 #include "base/test/bind.h"
9 #include "base/test/scoped_feature_list.h"
10 #include "base/test/task_environment.h"
11 #include "net/base/features.h"
12 #include "net/cookies/test_cookie_access_delegate.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17
18 using testing::UnorderedElementsAre;
19
TEST(CookiePartitionKeyCollectionTest,EmptySet)20 TEST(CookiePartitionKeyCollectionTest, EmptySet) {
21 CookiePartitionKeyCollection key_collection;
22
23 EXPECT_TRUE(key_collection.IsEmpty());
24 EXPECT_FALSE(key_collection.ContainsAllKeys());
25 EXPECT_EQ(0u, key_collection.PartitionKeys().size());
26 }
27
TEST(CookiePartitionKeyCollectionTest,SingletonSet)28 TEST(CookiePartitionKeyCollectionTest, SingletonSet) {
29 CookiePartitionKeyCollection key_collection(
30 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
31
32 EXPECT_FALSE(key_collection.IsEmpty());
33 EXPECT_FALSE(key_collection.ContainsAllKeys());
34 EXPECT_THAT(key_collection.PartitionKeys(),
35 UnorderedElementsAre(CookiePartitionKey::FromURLForTesting(
36 GURL("https://www.foo.com"))));
37 }
38
TEST(CookiePartitionKeyCollectionTest,MultipleElements)39 TEST(CookiePartitionKeyCollectionTest, MultipleElements) {
40 CookiePartitionKeyCollection key_collection({
41 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")),
42 CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com")),
43 });
44
45 EXPECT_FALSE(key_collection.IsEmpty());
46 EXPECT_FALSE(key_collection.ContainsAllKeys());
47 EXPECT_THAT(key_collection.PartitionKeys(),
48 UnorderedElementsAre(CookiePartitionKey::FromURLForTesting(
49 GURL("https://subdomain.foo.com")),
50 CookiePartitionKey::FromURLForTesting(
51 GURL("https://www.bar.com"))));
52 }
53
TEST(CookiePartitionKeyCollectionTest,ContainsAll)54 TEST(CookiePartitionKeyCollectionTest, ContainsAll) {
55 CookiePartitionKeyCollection key_collection =
56 CookiePartitionKeyCollection::ContainsAll();
57 EXPECT_FALSE(key_collection.IsEmpty());
58 EXPECT_TRUE(key_collection.ContainsAllKeys());
59 }
60
TEST(CookiePartitionKeyCollectionTest,FromOptional)61 TEST(CookiePartitionKeyCollectionTest, FromOptional) {
62 CookiePartitionKeyCollection key_collection =
63 CookiePartitionKeyCollection::FromOptional(std::nullopt);
64 EXPECT_TRUE(key_collection.IsEmpty());
65 EXPECT_FALSE(key_collection.ContainsAllKeys());
66
67 key_collection = CookiePartitionKeyCollection::FromOptional(
68 std::make_optional<CookiePartitionKey>(
69 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))));
70 EXPECT_FALSE(key_collection.IsEmpty());
71 EXPECT_FALSE(key_collection.ContainsAllKeys());
72 EXPECT_THAT(key_collection.PartitionKeys(),
73 UnorderedElementsAre(CookiePartitionKey::FromURLForTesting(
74 GURL("https://www.foo.com"))));
75 }
76
TEST(CookiePartitionKeyCollectionTest,Contains)77 TEST(CookiePartitionKeyCollectionTest, Contains) {
78 const CookiePartitionKey kPartitionKey =
79 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"));
80 const CookiePartitionKey kOtherPartitionKey =
81 CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com"));
82 const CookiePartitionKey kPartitionKeyNotInCollection =
83 CookiePartitionKey::FromURLForTesting(GURL("https://foobar.com"));
84 const CookiePartitionKey kDifferentAncestorChainValue =
85 CookiePartitionKey::FromURLForTesting(
86 GURL("https://foo.com"),
87 CookiePartitionKey::AncestorChainBit::kSameSite);
88
89 struct TestCase {
90 const CookiePartitionKeyCollection keychain;
91 const CookiePartitionKey key;
92 bool expects_contains;
93 } test_cases[] = {
94 // Empty keychain
95 {CookiePartitionKeyCollection(), kPartitionKey, false},
96 // Singleton keychain with key
97 {CookiePartitionKeyCollection(kPartitionKey), kPartitionKey, true},
98 // Singleton keychain with different key
99 {CookiePartitionKeyCollection(kOtherPartitionKey), kPartitionKey, false},
100 // Multiple keys
101 {CookiePartitionKeyCollection({kPartitionKey, kOtherPartitionKey}),
102 kPartitionKey, true},
103 // Key not in collection
104 {CookiePartitionKeyCollection({kPartitionKey, kOtherPartitionKey}),
105 kPartitionKeyNotInCollection, false},
106 // Same url but different CrossSiteAncestorChain value not in collection
107 {CookiePartitionKeyCollection({kPartitionKey, kOtherPartitionKey}),
108 kDifferentAncestorChainValue, false},
109 // Contains all keys
110 {CookiePartitionKeyCollection::ContainsAll(), kPartitionKey, true},
111 };
112 for (const auto& test_case : test_cases) {
113 EXPECT_EQ(test_case.expects_contains,
114 test_case.keychain.Contains(test_case.key));
115 }
116 }
117
TEST(CookiePartitionKeyCollectionTest,Equals)118 TEST(CookiePartitionKeyCollectionTest, Equals) {
119 CookiePartitionKeyCollection empty;
120 CookiePartitionKeyCollection foo(
121 CookiePartitionKey::FromURLForTesting(GURL("https://foo.test")));
122 CookiePartitionKeyCollection bar(
123 CookiePartitionKey::FromURLForTesting(GURL("https://bar.test")));
124 CookiePartitionKeyCollection all =
125 CookiePartitionKeyCollection::ContainsAll();
126
127 EXPECT_EQ(empty, empty);
128 EXPECT_EQ(foo, foo);
129 EXPECT_EQ(bar, bar);
130 EXPECT_EQ(all, all);
131
132 EXPECT_NE(foo, empty);
133 EXPECT_NE(empty, foo);
134
135 EXPECT_NE(foo, bar);
136 EXPECT_NE(bar, foo);
137
138 EXPECT_NE(foo, all);
139 EXPECT_NE(all, foo);
140 }
141
TEST(CookiePartitionKeyCollectionTest,ConsidersAncestorChainBit)142 TEST(CookiePartitionKeyCollectionTest, ConsidersAncestorChainBit) {
143 CookiePartitionKey cross_site_key = CookiePartitionKey::FromURLForTesting(
144 GURL("https://foo.test"),
145 CookiePartitionKey::AncestorChainBit::kCrossSite);
146
147 CookiePartitionKey same_site_key = CookiePartitionKey::FromURLForTesting(
148 GURL("https://foo.test"),
149 CookiePartitionKey::AncestorChainBit::kSameSite);
150
151 CookiePartitionKeyCollection cross_site_collection(cross_site_key);
152 CookiePartitionKeyCollection same_site_collection(same_site_key);
153 CookiePartitionKeyCollection all =
154 CookiePartitionKeyCollection::ContainsAll();
155
156 // Confirm that CookiePartitionKeyCollection::ContainsAll() is not impacted by
157 // the value of the AncestorChainBit.
158 EXPECT_TRUE(all.Contains(cross_site_key));
159 EXPECT_TRUE(all.Contains(same_site_key));
160
161 EXPECT_NE(cross_site_collection, same_site_collection);
162 EXPECT_FALSE(cross_site_collection.Contains(same_site_key));
163 EXPECT_FALSE(same_site_collection.Contains(cross_site_key));
164 }
165
TEST(CookiePartitionKeyCollectionTest,MatchesSite)166 TEST(CookiePartitionKeyCollectionTest, MatchesSite) {
167 GURL site = GURL("https://foo.test");
168 CookiePartitionKeyCollection collection =
169 CookiePartitionKeyCollection::MatchesSite(net::SchemefulSite(site));
170
171 struct {
172 CookiePartitionKey key;
173 bool expectation;
174 } cases[]{
175 {CookiePartitionKey::FromURLForTesting(
176 site, CookiePartitionKey::AncestorChainBit::kCrossSite),
177 true},
178 {CookiePartitionKey::FromURLForTesting(
179 site, CookiePartitionKey::AncestorChainBit::kSameSite),
180 true},
181 {CookiePartitionKey::FromURLForTesting(
182 GURL("https://example.com"),
183 CookiePartitionKey::AncestorChainBit::kSameSite),
184 false},
185 {CookiePartitionKey::FromURLForTesting(
186 GURL("https://example.com"),
187 CookiePartitionKey::AncestorChainBit::kCrossSite),
188 false},
189 };
190 for (const auto& tc : cases) {
191 EXPECT_EQ(collection.Contains(tc.key), tc.expectation);
192 }
193 }
194 } // namespace net
195