1 // Copyright 2018 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 #ifndef NET_COOKIES_COOKIE_STORE_CHANGE_UNITTEST_H_
6 #define NET_COOKIES_COOKIE_STORE_CHANGE_UNITTEST_H_
7
8 #include "base/functional/bind.h"
9 #include "net/cookies/canonical_cookie.h"
10 #include "net/cookies/cookie_change_dispatcher_test_helpers.h"
11 #include "net/cookies/cookie_constants.h"
12 #include "net/cookies/cookie_store.h"
13 #include "net/cookies/cookie_store_unittest.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "url/gurl.h"
16
17 namespace net {
18
19 namespace {
20
21 // Used to sort CookieChanges when testing stores without exact change ordering.
22 //
23 // The ordering relation must match the order in which the tests below issue
24 // cookie calls. Changes to this method should be tested by running the tests
25 // below with CookieMonsterTestTraits::has_exact_change_ordering set to both
26 // true and false.
CookieChangeLessThan(const CookieChangeInfo & lhs,const CookieChangeInfo & rhs)27 bool CookieChangeLessThan(const CookieChangeInfo& lhs,
28 const CookieChangeInfo& rhs) {
29 if (lhs.cookie.Name() != rhs.cookie.Name())
30 return lhs.cookie.Name() < rhs.cookie.Name();
31
32 if (lhs.cookie.Value() != rhs.cookie.Value())
33 return lhs.cookie.Value() < rhs.cookie.Value();
34
35 if (lhs.cookie.Domain() != rhs.cookie.Domain())
36 return lhs.cookie.Domain() < rhs.cookie.Domain();
37
38 return lhs.cause < rhs.cause;
39 }
40
41 } // namespace
42
43 // Google Test supports at most 50 tests per typed case, so the tests here are
44 // broken up into multiple cases.
45 template <class CookieStoreTestTraits>
46 class CookieStoreChangeTestBase
47 : public CookieStoreTest<CookieStoreTestTraits> {
48 protected:
49 using CookieStoreTest<CookieStoreTestTraits>::FindAndDeleteCookie;
50
51 // Drains all pending tasks on the run loop(s) involved in the test.
DeliverChangeNotifications()52 void DeliverChangeNotifications() {
53 CookieStoreTestTraits::DeliverChangeNotifications();
54 }
55
FindAndDeleteCookie(CookieStore * cs,const std::string & domain,const std::string & name,const std::string & path)56 bool FindAndDeleteCookie(CookieStore* cs,
57 const std::string& domain,
58 const std::string& name,
59 const std::string& path) {
60 for (auto& cookie : this->GetAllCookies(cs)) {
61 if (cookie.Domain() == domain && cookie.Name() == name &&
62 cookie.Path() == path) {
63 return this->DeleteCanonicalCookie(cs, cookie);
64 }
65 }
66
67 return false;
68 }
69
70 // Could be static, but it's actually easier to have it be a member function.
MatchesCause(CookieChangeCause expected_cause,CookieChangeCause actual_cause)71 ::testing::AssertionResult MatchesCause(CookieChangeCause expected_cause,
72 CookieChangeCause actual_cause) {
73 if (!CookieChangeCauseIsDeletion(expected_cause) ||
74 CookieStoreTestTraits::has_exact_change_cause) {
75 if (expected_cause == actual_cause)
76 return ::testing::AssertionSuccess();
77 return ::testing::AssertionFailure()
78 << "expected " << expected_cause << " got " << actual_cause;
79 }
80 if (CookieChangeCauseIsDeletion(actual_cause))
81 return ::testing::AssertionSuccess();
82 return ::testing::AssertionFailure()
83 << "expected a deletion cause, got " << actual_cause;
84 }
85
IsExpectedAccessSemantics(net::CookieAccessSemantics expected_semantics,net::CookieAccessSemantics actual_semantics)86 bool IsExpectedAccessSemantics(net::CookieAccessSemantics expected_semantics,
87 net::CookieAccessSemantics actual_semantics) {
88 if (CookieStoreTestTraits::supports_cookie_access_semantics)
89 return expected_semantics == actual_semantics;
90 return actual_semantics == net::CookieAccessSemantics::UNKNOWN;
91 }
92
OnCookieChange(std::vector<CookieChangeInfo> * changes,const CookieChangeInfo & notification)93 static void OnCookieChange(std::vector<CookieChangeInfo>* changes,
94 const CookieChangeInfo& notification) {
95 if (CookieStoreTestTraits::has_exact_change_ordering) {
96 changes->push_back(notification);
97 } else {
98 // Assumes the vector is sorted before the insertion. If true, the vector
99 // will remain sorted.
100 changes->insert(std::upper_bound(changes->begin(), changes->end(),
101 notification, CookieChangeLessThan),
102 notification);
103 }
104 }
105 };
106
107 template <class CookieStoreTestTraits>
108 class CookieStoreChangeGlobalTest
109 : public CookieStoreChangeTestBase<CookieStoreTestTraits> {};
110 TYPED_TEST_SUITE_P(CookieStoreChangeGlobalTest);
111
112 template <class CookieStoreTestTraits>
113 class CookieStoreChangeUrlTest
114 : public CookieStoreChangeTestBase<CookieStoreTestTraits> {};
115 TYPED_TEST_SUITE_P(CookieStoreChangeUrlTest);
116
117 template <class CookieStoreTestTraits>
118 class CookieStoreChangeNamedTest
119 : public CookieStoreChangeTestBase<CookieStoreTestTraits> {};
120 TYPED_TEST_SUITE_P(CookieStoreChangeNamedTest);
121
TYPED_TEST_P(CookieStoreChangeGlobalTest,NoCookie)122 TYPED_TEST_P(CookieStoreChangeGlobalTest, NoCookie) {
123 if (!TypeParam::supports_global_cookie_tracking)
124 return;
125
126 CookieStore* cs = this->GetCookieStore();
127 std::vector<CookieChangeInfo> cookie_changes;
128 std::unique_ptr<CookieChangeSubscription> subscription =
129 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
130 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
131 base::Unretained(&cookie_changes)));
132 this->DeliverChangeNotifications();
133 EXPECT_EQ(0u, cookie_changes.size());
134 }
135
TYPED_TEST_P(CookieStoreChangeGlobalTest,InitialCookie)136 TYPED_TEST_P(CookieStoreChangeGlobalTest, InitialCookie) {
137 if (!TypeParam::supports_global_cookie_tracking)
138 return;
139
140 CookieStore* cs = this->GetCookieStore();
141 std::vector<CookieChangeInfo> cookie_changes;
142 this->SetCookie(cs, this->http_www_foo_.url(), "A=B");
143 this->DeliverChangeNotifications();
144 std::unique_ptr<CookieChangeSubscription> subscription(
145 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
146 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
147 base::Unretained(&cookie_changes))));
148 this->DeliverChangeNotifications();
149 EXPECT_EQ(0u, cookie_changes.size());
150 }
151
TYPED_TEST_P(CookieStoreChangeGlobalTest,InsertOne)152 TYPED_TEST_P(CookieStoreChangeGlobalTest, InsertOne) {
153 if (!TypeParam::supports_global_cookie_tracking)
154 return;
155
156 CookieStore* cs = this->GetCookieStore();
157 std::vector<CookieChangeInfo> cookie_changes;
158 std::unique_ptr<CookieChangeSubscription> subscription =
159 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
160 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
161 base::Unretained(&cookie_changes)));
162 this->DeliverChangeNotifications();
163 ASSERT_EQ(0u, cookie_changes.size());
164
165 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
166 this->DeliverChangeNotifications();
167
168 ASSERT_EQ(1u, cookie_changes.size());
169 EXPECT_TRUE(
170 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
171 EXPECT_EQ(this->http_www_foo_.url().host(),
172 cookie_changes[0].cookie.Domain());
173 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
174 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
175 }
176
TYPED_TEST_P(CookieStoreChangeGlobalTest,InsertMany)177 TYPED_TEST_P(CookieStoreChangeGlobalTest, InsertMany) {
178 if (!TypeParam::supports_global_cookie_tracking)
179 return;
180
181 CookieStore* cs = this->GetCookieStore();
182 std::vector<CookieChangeInfo> cookie_changes;
183 std::unique_ptr<CookieChangeSubscription> subscription =
184 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
185 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
186 base::Unretained(&cookie_changes)));
187 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
188 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
189 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F"));
190 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "G=H"));
191 this->DeliverChangeNotifications();
192
193 // Check that the cookie changes are dispatched before calling GetCookies.
194 // This is not an ASSERT because the following expectations produce useful
195 // debugging information if they fail.
196 EXPECT_EQ(4u, cookie_changes.size());
197 EXPECT_EQ("A=B; C=D; E=F", this->GetCookies(cs, this->http_www_foo_.url()));
198 EXPECT_EQ("G=H", this->GetCookies(cs, this->http_bar_com_.url()));
199
200 ASSERT_LE(1u, cookie_changes.size());
201 EXPECT_TRUE(
202 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
203 EXPECT_EQ(this->http_www_foo_.url().host(),
204 cookie_changes[0].cookie.Domain());
205 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
206 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
207
208 ASSERT_LE(2u, cookie_changes.size());
209 EXPECT_EQ(this->http_www_foo_.url().host(),
210 cookie_changes[1].cookie.Domain());
211 EXPECT_TRUE(
212 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
213 EXPECT_EQ("C", cookie_changes[1].cookie.Name());
214 EXPECT_EQ("D", cookie_changes[1].cookie.Value());
215
216 ASSERT_LE(3u, cookie_changes.size());
217 EXPECT_EQ(this->http_www_foo_.url().host(),
218 cookie_changes[2].cookie.Domain());
219 EXPECT_TRUE(
220 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[2].cause));
221 EXPECT_EQ("E", cookie_changes[2].cookie.Name());
222 EXPECT_EQ("F", cookie_changes[2].cookie.Value());
223
224 ASSERT_LE(4u, cookie_changes.size());
225 EXPECT_EQ(this->http_bar_com_.url().host(),
226 cookie_changes[3].cookie.Domain());
227 EXPECT_TRUE(
228 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[3].cause));
229 EXPECT_EQ("G", cookie_changes[3].cookie.Name());
230 EXPECT_EQ("H", cookie_changes[3].cookie.Value());
231
232 EXPECT_EQ(4u, cookie_changes.size());
233 }
234
TYPED_TEST_P(CookieStoreChangeGlobalTest,DeleteOne)235 TYPED_TEST_P(CookieStoreChangeGlobalTest, DeleteOne) {
236 if (!TypeParam::supports_global_cookie_tracking)
237 return;
238
239 CookieStore* cs = this->GetCookieStore();
240 std::vector<CookieChangeInfo> cookie_changes;
241 std::unique_ptr<CookieChangeSubscription> subscription =
242 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
243 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
244 base::Unretained(&cookie_changes)));
245 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
246 this->DeliverChangeNotifications();
247 EXPECT_EQ(1u, cookie_changes.size());
248 cookie_changes.clear();
249
250 EXPECT_TRUE(
251 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "A"));
252 this->DeliverChangeNotifications();
253
254 ASSERT_EQ(1u, cookie_changes.size());
255 EXPECT_EQ(this->http_www_foo_.url().host(),
256 cookie_changes[0].cookie.Domain());
257 EXPECT_TRUE(
258 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
259 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
260 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
261 }
262
TYPED_TEST_P(CookieStoreChangeGlobalTest,DeleteTwo)263 TYPED_TEST_P(CookieStoreChangeGlobalTest, DeleteTwo) {
264 if (!TypeParam::supports_global_cookie_tracking)
265 return;
266
267 CookieStore* cs = this->GetCookieStore();
268 std::vector<CookieChangeInfo> cookie_changes;
269 std::unique_ptr<CookieChangeSubscription> subscription =
270 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
271 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
272 base::Unretained(&cookie_changes)));
273 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
274 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
275 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F"));
276 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "G=H"));
277 this->DeliverChangeNotifications();
278 EXPECT_EQ(4u, cookie_changes.size());
279 cookie_changes.clear();
280
281 EXPECT_TRUE(
282 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "C"));
283 EXPECT_TRUE(
284 this->FindAndDeleteCookie(cs, this->http_bar_com_.url().host(), "G"));
285 this->DeliverChangeNotifications();
286
287 // Check that the cookie changes are dispatched before calling GetCookies.
288 // This is not an ASSERT because the following expectations produce useful
289 // debugging information if they fail.
290 EXPECT_EQ(2u, cookie_changes.size());
291 EXPECT_EQ("A=B; E=F", this->GetCookies(cs, this->http_www_foo_.url()));
292 EXPECT_EQ("", this->GetCookies(cs, this->http_bar_com_.url()));
293
294 ASSERT_LE(1u, cookie_changes.size());
295 EXPECT_EQ(this->http_www_foo_.url().host(),
296 cookie_changes[0].cookie.Domain());
297 EXPECT_TRUE(
298 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
299 EXPECT_EQ("C", cookie_changes[0].cookie.Name());
300 EXPECT_EQ("D", cookie_changes[0].cookie.Value());
301
302 ASSERT_EQ(2u, cookie_changes.size());
303 EXPECT_EQ(this->http_bar_com_.url().host(),
304 cookie_changes[1].cookie.Domain());
305 EXPECT_TRUE(
306 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[1].cause));
307 EXPECT_EQ("G", cookie_changes[1].cookie.Name());
308 EXPECT_EQ("H", cookie_changes[1].cookie.Value());
309 }
310
TYPED_TEST_P(CookieStoreChangeGlobalTest,Overwrite)311 TYPED_TEST_P(CookieStoreChangeGlobalTest, Overwrite) {
312 if (!TypeParam::supports_global_cookie_tracking)
313 return;
314
315 CookieStore* cs = this->GetCookieStore();
316 std::vector<CookieChangeInfo> cookie_changes;
317 std::unique_ptr<CookieChangeSubscription> subscription =
318 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
319 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
320 base::Unretained(&cookie_changes)));
321 this->DeliverChangeNotifications();
322 ASSERT_EQ(0u, cookie_changes.size());
323
324 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
325 this->DeliverChangeNotifications();
326 ASSERT_EQ(1u, cookie_changes.size());
327 cookie_changes.clear();
328
329 // Replacing an existing cookie is actually a two-phase delete + set
330 // operation, so we get an extra notification.
331 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C"));
332 this->DeliverChangeNotifications();
333
334 ASSERT_LE(1u, cookie_changes.size());
335 EXPECT_EQ(this->http_www_foo_.url().host(),
336 cookie_changes[0].cookie.Domain());
337 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
338 cookie_changes[0].cause));
339 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
340 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
341
342 ASSERT_LE(2u, cookie_changes.size());
343 EXPECT_EQ(this->http_www_foo_.url().host(),
344 cookie_changes[1].cookie.Domain());
345 EXPECT_TRUE(
346 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
347 EXPECT_EQ("A", cookie_changes[1].cookie.Name());
348 EXPECT_EQ("C", cookie_changes[1].cookie.Value());
349
350 EXPECT_EQ(2u, cookie_changes.size());
351 }
352
TYPED_TEST_P(CookieStoreChangeGlobalTest,OverwriteWithHttpOnly)353 TYPED_TEST_P(CookieStoreChangeGlobalTest, OverwriteWithHttpOnly) {
354 if (!TypeParam::supports_global_cookie_tracking)
355 return;
356
357 // Insert a cookie "A" for path "/path1"
358 CookieStore* cs = this->GetCookieStore();
359 std::vector<CookieChangeInfo> cookie_changes;
360 std::unique_ptr<CookieChangeSubscription> subscription =
361 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
362 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
363 base::Unretained(&cookie_changes)));
364 this->DeliverChangeNotifications();
365 ASSERT_EQ(0u, cookie_changes.size());
366
367 EXPECT_TRUE(
368 this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/path1"));
369 this->DeliverChangeNotifications();
370 ASSERT_EQ(1u, cookie_changes.size());
371 EXPECT_TRUE(
372 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
373 EXPECT_EQ(this->http_www_foo_.url().host(),
374 cookie_changes[0].cookie.Domain());
375 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
376 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
377 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
378 cookie_changes.clear();
379
380 // Insert a cookie "A" for path "/path1", that is httponly. This should
381 // overwrite the non-http-only version.
382 CookieOptions allow_httponly;
383 allow_httponly.set_include_httponly();
384 allow_httponly.set_same_site_cookie_context(
385 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
386
387 EXPECT_TRUE(this->CreateAndSetCookie(cs, this->http_www_foo_.url(),
388 "A=C; path=/path1; httponly",
389 allow_httponly));
390 this->DeliverChangeNotifications();
391
392 ASSERT_LE(1u, cookie_changes.size());
393 EXPECT_EQ(this->http_www_foo_.url().host(),
394 cookie_changes[0].cookie.Domain());
395 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
396 cookie_changes[0].cause));
397 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
398 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
399 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
400
401 ASSERT_LE(2u, cookie_changes.size());
402 EXPECT_EQ(this->http_www_foo_.url().host(),
403 cookie_changes[1].cookie.Domain());
404 EXPECT_TRUE(
405 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
406 EXPECT_EQ("A", cookie_changes[1].cookie.Name());
407 EXPECT_EQ("C", cookie_changes[1].cookie.Value());
408 EXPECT_TRUE(cookie_changes[1].cookie.IsHttpOnly());
409
410 EXPECT_EQ(2u, cookie_changes.size());
411 }
412
TYPED_TEST_P(CookieStoreChangeGlobalTest,Deregister)413 TYPED_TEST_P(CookieStoreChangeGlobalTest, Deregister) {
414 if (!TypeParam::supports_global_cookie_tracking)
415 return;
416
417 CookieStore* cs = this->GetCookieStore();
418
419 std::vector<CookieChangeInfo> cookie_changes;
420 std::unique_ptr<CookieChangeSubscription> subscription =
421 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
422 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
423 base::Unretained(&cookie_changes)));
424 this->DeliverChangeNotifications();
425 ASSERT_EQ(0u, cookie_changes.size());
426
427 // Insert a cookie and make sure it is seen.
428 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
429 this->DeliverChangeNotifications();
430 ASSERT_EQ(1u, cookie_changes.size());
431 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
432 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
433 cookie_changes.clear();
434
435 // De-register the subscription.
436 subscription.reset();
437
438 // Insert a second cookie and make sure that it's not visible.
439 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
440 this->DeliverChangeNotifications();
441
442 EXPECT_EQ(0u, cookie_changes.size());
443 }
444
TYPED_TEST_P(CookieStoreChangeGlobalTest,DeregisterMultiple)445 TYPED_TEST_P(CookieStoreChangeGlobalTest, DeregisterMultiple) {
446 if (!TypeParam::supports_global_cookie_tracking ||
447 !TypeParam::supports_multiple_tracking_callbacks)
448 return;
449
450 CookieStore* cs = this->GetCookieStore();
451
452 // Register two subscriptions.
453 std::vector<CookieChangeInfo> cookie_changes_1;
454 std::unique_ptr<CookieChangeSubscription> subscription1 =
455 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
456 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
457 base::Unretained(&cookie_changes_1)));
458
459 std::vector<CookieChangeInfo> cookie_changes_2;
460 std::unique_ptr<CookieChangeSubscription> subscription2 =
461 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
462 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
463 base::Unretained(&cookie_changes_2)));
464 this->DeliverChangeNotifications();
465 ASSERT_EQ(0u, cookie_changes_1.size());
466 ASSERT_EQ(0u, cookie_changes_2.size());
467
468 // Insert a cookie and make sure it's seen.
469 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
470 this->DeliverChangeNotifications();
471 ASSERT_EQ(1u, cookie_changes_1.size());
472 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
473 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
474 cookie_changes_1.clear();
475
476 ASSERT_EQ(1u, cookie_changes_2.size());
477 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
478 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
479 cookie_changes_2.clear();
480
481 // De-register the second subscription.
482 subscription2.reset();
483
484 // Insert a second cookie and make sure that it's only visible in one
485 // change array.
486 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
487 this->DeliverChangeNotifications();
488 ASSERT_EQ(1u, cookie_changes_1.size());
489 EXPECT_EQ("C", cookie_changes_1[0].cookie.Name());
490 EXPECT_EQ("D", cookie_changes_1[0].cookie.Value());
491 cookie_changes_1.clear();
492
493 ASSERT_EQ(0u, cookie_changes_2.size());
494 }
495
496 // Confirm that a listener does not receive notifications for changes that
497 // happened right before the subscription was established.
TYPED_TEST_P(CookieStoreChangeGlobalTest,DispatchRace)498 TYPED_TEST_P(CookieStoreChangeGlobalTest, DispatchRace) {
499 if (!TypeParam::supports_global_cookie_tracking)
500 return;
501
502 CookieStore* cs = this->GetCookieStore();
503
504 // This cookie insertion should not be seen.
505 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
506 // DeliverChangeNotifications() must NOT be called before the subscription is
507 // established.
508
509 std::vector<CookieChangeInfo> cookie_changes;
510 std::unique_ptr<CookieChangeSubscription> subscription =
511 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
512 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
513 base::Unretained(&cookie_changes)));
514
515 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
516 this->DeliverChangeNotifications();
517
518 EXPECT_LE(1u, cookie_changes.size());
519 EXPECT_EQ("C", cookie_changes[0].cookie.Name());
520 EXPECT_EQ("D", cookie_changes[0].cookie.Value());
521
522 ASSERT_EQ(1u, cookie_changes.size());
523 }
524
525 // Confirm that deregistering a subscription blocks the notification if the
526 // deregistration happened after the change but before the notification was
527 // received.
TYPED_TEST_P(CookieStoreChangeGlobalTest,DeregisterRace)528 TYPED_TEST_P(CookieStoreChangeGlobalTest, DeregisterRace) {
529 if (!TypeParam::supports_global_cookie_tracking)
530 return;
531
532 CookieStore* cs = this->GetCookieStore();
533
534 std::vector<CookieChangeInfo> cookie_changes;
535 std::unique_ptr<CookieChangeSubscription> subscription =
536 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
537 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
538 base::Unretained(&cookie_changes)));
539 this->DeliverChangeNotifications();
540 ASSERT_EQ(0u, cookie_changes.size());
541
542 // Insert a cookie and make sure it's seen.
543 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
544 this->DeliverChangeNotifications();
545 ASSERT_EQ(1u, cookie_changes.size());
546 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
547 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
548 cookie_changes.clear();
549
550 // Insert a cookie, confirm it is not seen, deregister the subscription, run
551 // until idle, and confirm the cookie is still not seen.
552 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
553
554 // Note that by the API contract it's perfectly valid to have received the
555 // notification immediately, i.e. synchronously with the cookie change. In
556 // that case, there's nothing to test.
557 if (1u == cookie_changes.size())
558 return;
559
560 // A task was posted by the SetCookie() above, but has not yet arrived. If it
561 // arrived before the subscription is destroyed, callback execution would be
562 // valid. Destroy the subscription so as to lose the race and make sure the
563 // task posted arrives after the subscription was destroyed.
564 subscription.reset();
565 this->DeliverChangeNotifications();
566 ASSERT_EQ(0u, cookie_changes.size());
567 }
568
TYPED_TEST_P(CookieStoreChangeGlobalTest,DeregisterRaceMultiple)569 TYPED_TEST_P(CookieStoreChangeGlobalTest, DeregisterRaceMultiple) {
570 if (!TypeParam::supports_global_cookie_tracking ||
571 !TypeParam::supports_multiple_tracking_callbacks)
572 return;
573
574 CookieStore* cs = this->GetCookieStore();
575
576 // Register two subscriptions.
577 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
578 std::unique_ptr<CookieChangeSubscription> subscription1 =
579 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
580 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
581 base::Unretained(&cookie_changes_1)));
582 std::unique_ptr<CookieChangeSubscription> subscription2 =
583 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
584 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
585 base::Unretained(&cookie_changes_2)));
586 this->DeliverChangeNotifications();
587 ASSERT_EQ(0u, cookie_changes_1.size());
588 ASSERT_EQ(0u, cookie_changes_2.size());
589
590 // Insert a cookie and make sure it's seen.
591 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
592 this->DeliverChangeNotifications();
593
594 ASSERT_EQ(1u, cookie_changes_1.size());
595 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
596 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
597 cookie_changes_1.clear();
598
599 ASSERT_EQ(1u, cookie_changes_2.size());
600 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
601 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
602 cookie_changes_2.clear();
603
604 // Insert a cookie, confirm it is not seen, deregister a subscription, run
605 // until idle, and confirm the cookie is still not seen.
606 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
607
608 // Note that by the API contract it's perfectly valid to have received the
609 // notification immediately, i.e. synchronously with the cookie change. In
610 // that case, there's nothing to test.
611 if (1u == cookie_changes_2.size())
612 return;
613
614 // A task was posted by the SetCookie() above, but has not yet arrived. If it
615 // arrived before the subscription is destroyed, callback execution would be
616 // valid. Destroy one of the subscriptions so as to lose the race and make
617 // sure the task posted arrives after the subscription was destroyed.
618 subscription2.reset();
619 this->DeliverChangeNotifications();
620 ASSERT_EQ(1u, cookie_changes_1.size());
621 EXPECT_EQ("C", cookie_changes_1[0].cookie.Name());
622 EXPECT_EQ("D", cookie_changes_1[0].cookie.Value());
623
624 // No late notification was received.
625 ASSERT_EQ(0u, cookie_changes_2.size());
626 }
627
TYPED_TEST_P(CookieStoreChangeGlobalTest,MultipleSubscriptions)628 TYPED_TEST_P(CookieStoreChangeGlobalTest, MultipleSubscriptions) {
629 if (!TypeParam::supports_global_cookie_tracking ||
630 !TypeParam::supports_multiple_tracking_callbacks)
631 return;
632
633 CookieStore* cs = this->GetCookieStore();
634
635 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
636 std::unique_ptr<CookieChangeSubscription> subscription1 =
637 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
638 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
639 base::Unretained(&cookie_changes_1)));
640 std::unique_ptr<CookieChangeSubscription> subscription2 =
641 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
642 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
643 base::Unretained(&cookie_changes_2)));
644 this->DeliverChangeNotifications();
645
646 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
647 this->DeliverChangeNotifications();
648
649 ASSERT_EQ(1U, cookie_changes_1.size());
650 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
651 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
652
653 ASSERT_EQ(1U, cookie_changes_2.size());
654 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
655 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
656 }
657
TYPED_TEST_P(CookieStoreChangeGlobalTest,ChangeIncludesCookieAccessSemantics)658 TYPED_TEST_P(CookieStoreChangeGlobalTest, ChangeIncludesCookieAccessSemantics) {
659 if (!TypeParam::supports_global_cookie_tracking)
660 return;
661
662 CookieStore* cs = this->GetCookieStore();
663 // if !supports_cookie_access_semantics, the delegate will be stored but will
664 // not be used.
665 auto access_delegate = std::make_unique<TestCookieAccessDelegate>();
666 access_delegate->SetExpectationForCookieDomain("domain1.test",
667 CookieAccessSemantics::LEGACY);
668 access_delegate->SetExpectationForCookieDomain(
669 "domain2.test", CookieAccessSemantics::NONLEGACY);
670 access_delegate->SetExpectationForCookieDomain(
671 "domain3.test", CookieAccessSemantics::UNKNOWN);
672 cs->SetCookieAccessDelegate(std::move(access_delegate));
673
674 std::vector<CookieChangeInfo> cookie_changes;
675 std::unique_ptr<CookieChangeSubscription> subscription =
676 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
677 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
678 base::Unretained(&cookie_changes)));
679
680 this->CreateAndSetCookie(cs, GURL("http://domain1.test"), "cookie=1",
681 CookieOptions::MakeAllInclusive());
682 this->CreateAndSetCookie(cs, GURL("http://domain2.test"), "cookie=1",
683 CookieOptions::MakeAllInclusive());
684 this->CreateAndSetCookie(cs, GURL("http://domain3.test"), "cookie=1",
685 CookieOptions::MakeAllInclusive());
686 this->CreateAndSetCookie(cs, GURL("http://domain4.test"), "cookie=1",
687 CookieOptions::MakeAllInclusive());
688 this->DeliverChangeNotifications();
689
690 ASSERT_EQ(4u, cookie_changes.size());
691
692 EXPECT_EQ("domain1.test", cookie_changes[0].cookie.Domain());
693 EXPECT_TRUE(this->IsExpectedAccessSemantics(
694 CookieAccessSemantics::LEGACY,
695 cookie_changes[0].access_result.access_semantics));
696 EXPECT_EQ("domain2.test", cookie_changes[1].cookie.Domain());
697 EXPECT_TRUE(this->IsExpectedAccessSemantics(
698 CookieAccessSemantics::NONLEGACY,
699 cookie_changes[1].access_result.access_semantics));
700 EXPECT_EQ("domain3.test", cookie_changes[2].cookie.Domain());
701 EXPECT_TRUE(this->IsExpectedAccessSemantics(
702 CookieAccessSemantics::UNKNOWN,
703 cookie_changes[2].access_result.access_semantics));
704 EXPECT_EQ("domain4.test", cookie_changes[3].cookie.Domain());
705 EXPECT_TRUE(this->IsExpectedAccessSemantics(
706 CookieAccessSemantics::UNKNOWN,
707 cookie_changes[3].access_result.access_semantics));
708 }
709
TYPED_TEST_P(CookieStoreChangeGlobalTest,PartitionedCookies)710 TYPED_TEST_P(CookieStoreChangeGlobalTest, PartitionedCookies) {
711 if (!TypeParam::supports_named_cookie_tracking ||
712 !TypeParam::supports_partitioned_cookies) {
713 return;
714 }
715
716 CookieStore* cs = this->GetCookieStore();
717
718 // Test that all partitioned cookies are visible to global change listeners.
719 std::vector<CookieChangeInfo> all_cookie_changes;
720 std::unique_ptr<CookieChangeSubscription> global_subscription =
721 cs->GetChangeDispatcher().AddCallbackForAllChanges(base::BindRepeating(
722 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
723 base::Unretained(&all_cookie_changes)));
724 // Set two cookies in two separate partitions, one with nonce.
725 this->CreateAndSetCookie(
726 cs, GURL("https://www.example2.com"),
727 "__Host-a=1; Secure; Path=/; Partitioned",
728 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
729 std::nullopt /* system_time */,
730 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
731 this->CreateAndSetCookie(
732 cs, GURL("https://www.example2.com"),
733 "__Host-a=2; Secure; Path=/; Partitioned; Max-Age=7200",
734 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
735 std::nullopt /* system_time */,
736 CookiePartitionKey::FromURLForTesting(
737 GURL("https://www.bar.com"),
738 CookiePartitionKey::AncestorChainBit::kCrossSite,
739 base::UnguessableToken::Create()));
740 this->DeliverChangeNotifications();
741 ASSERT_EQ(2u, all_cookie_changes.size());
742 }
743
TYPED_TEST_P(CookieStoreChangeUrlTest,NoCookie)744 TYPED_TEST_P(CookieStoreChangeUrlTest, NoCookie) {
745 if (!TypeParam::supports_url_cookie_tracking)
746 return;
747
748 CookieStore* cs = this->GetCookieStore();
749 std::vector<CookieChangeInfo> cookie_changes;
750 std::unique_ptr<CookieChangeSubscription> subscription =
751 cs->GetChangeDispatcher().AddCallbackForUrl(
752 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
753 base::BindRepeating(
754 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
755 base::Unretained(&cookie_changes)));
756 this->DeliverChangeNotifications();
757 EXPECT_EQ(0u, cookie_changes.size());
758 }
759
TYPED_TEST_P(CookieStoreChangeUrlTest,InitialCookie)760 TYPED_TEST_P(CookieStoreChangeUrlTest, InitialCookie) {
761 if (!TypeParam::supports_url_cookie_tracking)
762 return;
763
764 CookieStore* cs = this->GetCookieStore();
765 std::vector<CookieChangeInfo> cookie_changes;
766 this->SetCookie(cs, this->http_www_foo_.url(), "A=B");
767 this->DeliverChangeNotifications();
768 std::unique_ptr<CookieChangeSubscription> subscription =
769 cs->GetChangeDispatcher().AddCallbackForUrl(
770 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
771 base::BindRepeating(
772 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
773 base::Unretained(&cookie_changes)));
774 this->DeliverChangeNotifications();
775 EXPECT_EQ(0u, cookie_changes.size());
776 }
777
TYPED_TEST_P(CookieStoreChangeUrlTest,InsertOne)778 TYPED_TEST_P(CookieStoreChangeUrlTest, InsertOne) {
779 if (!TypeParam::supports_url_cookie_tracking)
780 return;
781
782 CookieStore* cs = this->GetCookieStore();
783 std::vector<CookieChangeInfo> cookie_changes;
784 std::unique_ptr<CookieChangeSubscription> subscription =
785 cs->GetChangeDispatcher().AddCallbackForUrl(
786 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
787 base::BindRepeating(
788 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
789 base::Unretained(&cookie_changes)));
790 this->DeliverChangeNotifications();
791 ASSERT_EQ(0u, cookie_changes.size());
792
793 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
794 this->DeliverChangeNotifications();
795 ASSERT_EQ(1u, cookie_changes.size());
796
797 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
798 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
799 EXPECT_EQ(this->http_www_foo_.url().host(),
800 cookie_changes[0].cookie.Domain());
801 EXPECT_TRUE(
802 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
803 }
804
TYPED_TEST_P(CookieStoreChangeUrlTest,InsertMany)805 TYPED_TEST_P(CookieStoreChangeUrlTest, InsertMany) {
806 if (!TypeParam::supports_url_cookie_tracking)
807 return;
808
809 CookieStore* cs = this->GetCookieStore();
810 std::vector<CookieChangeInfo> cookie_changes;
811 std::unique_ptr<CookieChangeSubscription> subscription =
812 cs->GetChangeDispatcher().AddCallbackForUrl(
813 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
814 base::BindRepeating(
815 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
816 base::Unretained(&cookie_changes)));
817 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
818 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
819 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F"));
820 this->DeliverChangeNotifications();
821
822 ASSERT_LE(1u, cookie_changes.size());
823 EXPECT_TRUE(
824 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
825 EXPECT_EQ(this->http_www_foo_.url().host(),
826 cookie_changes[0].cookie.Domain());
827 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
828 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
829
830 ASSERT_LE(2u, cookie_changes.size());
831 EXPECT_EQ(this->http_www_foo_.url().host(),
832 cookie_changes[1].cookie.Domain());
833 EXPECT_TRUE(
834 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
835 EXPECT_EQ("C", cookie_changes[1].cookie.Name());
836 EXPECT_EQ("D", cookie_changes[1].cookie.Value());
837
838 ASSERT_LE(3u, cookie_changes.size());
839 EXPECT_EQ(this->http_www_foo_.url().host(),
840 cookie_changes[2].cookie.Domain());
841 EXPECT_TRUE(
842 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[2].cause));
843 EXPECT_EQ("E", cookie_changes[2].cookie.Name());
844 EXPECT_EQ("F", cookie_changes[2].cookie.Value());
845
846 EXPECT_EQ(3u, cookie_changes.size());
847 }
848
TYPED_TEST_P(CookieStoreChangeUrlTest,InsertFiltering)849 TYPED_TEST_P(CookieStoreChangeUrlTest, InsertFiltering) {
850 if (!TypeParam::supports_url_cookie_tracking)
851 return;
852
853 CookieStore* cs = this->GetCookieStore();
854 std::vector<CookieChangeInfo> cookie_changes;
855 std::unique_ptr<CookieChangeSubscription> subscription =
856 cs->GetChangeDispatcher().AddCallbackForUrl(
857 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
858 base::BindRepeating(
859 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
860 base::Unretained(&cookie_changes)));
861 this->DeliverChangeNotifications();
862 ASSERT_EQ(0u, cookie_changes.size());
863
864 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/"));
865 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D; path=/"));
866 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F; path=/bar"));
867 EXPECT_TRUE(
868 this->SetCookie(cs, this->http_www_foo_.url(), "G=H; path=/foo/bar"));
869 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "I=J; path=/foo"));
870 EXPECT_TRUE(
871 this->SetCookie(cs, this->http_www_foo_.url(), "K=L; domain=foo.com"));
872 this->DeliverChangeNotifications();
873
874 ASSERT_LE(1u, cookie_changes.size());
875 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
876 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
877 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
878 EXPECT_EQ(this->http_www_foo_.url().host(),
879 cookie_changes[0].cookie.Domain());
880 EXPECT_TRUE(
881 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
882
883 ASSERT_LE(2u, cookie_changes.size());
884 EXPECT_EQ("I", cookie_changes[1].cookie.Name());
885 EXPECT_EQ("J", cookie_changes[1].cookie.Value());
886 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
887 EXPECT_EQ(this->http_www_foo_.url().host(),
888 cookie_changes[1].cookie.Domain());
889 EXPECT_TRUE(
890 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
891
892 ASSERT_LE(3u, cookie_changes.size());
893 EXPECT_EQ("K", cookie_changes[2].cookie.Name());
894 EXPECT_EQ("L", cookie_changes[2].cookie.Value());
895 EXPECT_EQ("/", cookie_changes[2].cookie.Path());
896 EXPECT_EQ(".foo.com", cookie_changes[2].cookie.Domain());
897 EXPECT_TRUE(
898 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[2].cause));
899
900 EXPECT_EQ(3u, cookie_changes.size());
901 }
902
TYPED_TEST_P(CookieStoreChangeUrlTest,DeleteOne)903 TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteOne) {
904 if (!TypeParam::supports_url_cookie_tracking)
905 return;
906
907 CookieStore* cs = this->GetCookieStore();
908 std::vector<CookieChangeInfo> cookie_changes;
909 std::unique_ptr<CookieChangeSubscription> subscription =
910 cs->GetChangeDispatcher().AddCallbackForUrl(
911 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
912 base::BindRepeating(
913 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
914 base::Unretained(&cookie_changes)));
915 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
916 this->DeliverChangeNotifications();
917 EXPECT_EQ(1u, cookie_changes.size());
918 cookie_changes.clear();
919
920 EXPECT_TRUE(
921 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "A"));
922 this->DeliverChangeNotifications();
923
924 ASSERT_EQ(1u, cookie_changes.size());
925 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
926 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
927 EXPECT_EQ(this->http_www_foo_.url().host(),
928 cookie_changes[0].cookie.Domain());
929 ASSERT_TRUE(
930 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
931 }
932
TYPED_TEST_P(CookieStoreChangeUrlTest,DeleteTwo)933 TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteTwo) {
934 if (!TypeParam::supports_url_cookie_tracking)
935 return;
936
937 CookieStore* cs = this->GetCookieStore();
938 std::vector<CookieChangeInfo> cookie_changes;
939 std::unique_ptr<CookieChangeSubscription> subscription =
940 cs->GetChangeDispatcher().AddCallbackForUrl(
941 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
942 base::BindRepeating(
943 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
944 base::Unretained(&cookie_changes)));
945 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
946 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
947 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F"));
948 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "G=H"));
949 this->DeliverChangeNotifications();
950 EXPECT_EQ(4u, cookie_changes.size());
951 cookie_changes.clear();
952
953 EXPECT_TRUE(
954 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "C"));
955 EXPECT_TRUE(
956 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "G"));
957 this->DeliverChangeNotifications();
958
959 // Check that the cookie changes are dispatched before calling GetCookies.
960 // This is not an ASSERT because the following expectations produce useful
961 // debugging information if they fail.
962 EXPECT_EQ(2u, cookie_changes.size());
963 EXPECT_EQ("A=B; E=F", this->GetCookies(cs, this->http_www_foo_.url()));
964
965 ASSERT_LE(1u, cookie_changes.size());
966 EXPECT_EQ(this->http_www_foo_.url().host(),
967 cookie_changes[0].cookie.Domain());
968 EXPECT_TRUE(
969 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
970 EXPECT_EQ("C", cookie_changes[0].cookie.Name());
971 EXPECT_EQ("D", cookie_changes[0].cookie.Value());
972
973 ASSERT_EQ(2u, cookie_changes.size());
974 EXPECT_EQ(this->http_www_foo_.url().host(),
975 cookie_changes[1].cookie.Domain());
976 EXPECT_TRUE(
977 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[1].cause));
978 EXPECT_EQ("G", cookie_changes[1].cookie.Name());
979 EXPECT_EQ("H", cookie_changes[1].cookie.Value());
980 }
981
TYPED_TEST_P(CookieStoreChangeUrlTest,DeleteFiltering)982 TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteFiltering) {
983 if (!TypeParam::supports_url_cookie_tracking)
984 return;
985
986 CookieStore* cs = this->GetCookieStore();
987 std::vector<CookieChangeInfo> cookie_changes;
988 std::unique_ptr<CookieChangeSubscription> subscription =
989 cs->GetChangeDispatcher().AddCallbackForUrl(
990 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
991 base::BindRepeating(
992 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
993 base::Unretained(&cookie_changes)));
994 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/"));
995 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D; path=/"));
996 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F; path=/bar"));
997 EXPECT_TRUE(
998 this->SetCookie(cs, this->http_www_foo_.url(), "G=H; path=/foo/bar"));
999 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "I=J; path=/foo"));
1000 EXPECT_TRUE(
1001 this->SetCookie(cs, this->http_www_foo_.url(), "K=L; domain=foo.com"));
1002 this->DeliverChangeNotifications();
1003 EXPECT_EQ(3u, cookie_changes.size());
1004 cookie_changes.clear();
1005
1006 EXPECT_TRUE(
1007 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "A"));
1008 EXPECT_TRUE(
1009 this->FindAndDeleteCookie(cs, this->http_bar_com_.url().host(), "C"));
1010 EXPECT_TRUE(
1011 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "E"));
1012 EXPECT_TRUE(
1013 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "G"));
1014 EXPECT_TRUE(
1015 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "I"));
1016 EXPECT_TRUE(this->FindAndDeleteCookie(cs, ".foo.com", "K"));
1017 this->DeliverChangeNotifications();
1018
1019 ASSERT_LE(1u, cookie_changes.size());
1020 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1021 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1022 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
1023 EXPECT_EQ(this->http_www_foo_.url().host(),
1024 cookie_changes[0].cookie.Domain());
1025 EXPECT_TRUE(
1026 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
1027
1028 ASSERT_LE(2u, cookie_changes.size());
1029 EXPECT_EQ("I", cookie_changes[1].cookie.Name());
1030 EXPECT_EQ("J", cookie_changes[1].cookie.Value());
1031 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
1032 EXPECT_EQ(this->http_www_foo_.url().host(),
1033 cookie_changes[1].cookie.Domain());
1034 EXPECT_TRUE(
1035 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[1].cause));
1036
1037 ASSERT_LE(3u, cookie_changes.size());
1038 EXPECT_EQ("K", cookie_changes[2].cookie.Name());
1039 EXPECT_EQ("L", cookie_changes[2].cookie.Value());
1040 EXPECT_EQ("/", cookie_changes[2].cookie.Path());
1041 EXPECT_EQ(".foo.com", cookie_changes[2].cookie.Domain());
1042 EXPECT_TRUE(
1043 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[2].cause));
1044
1045 EXPECT_EQ(3u, cookie_changes.size());
1046 }
1047
TYPED_TEST_P(CookieStoreChangeUrlTest,Overwrite)1048 TYPED_TEST_P(CookieStoreChangeUrlTest, Overwrite) {
1049 if (!TypeParam::supports_url_cookie_tracking)
1050 return;
1051
1052 CookieStore* cs = this->GetCookieStore();
1053 std::vector<CookieChangeInfo> cookie_changes;
1054 std::unique_ptr<CookieChangeSubscription> subscription =
1055 cs->GetChangeDispatcher().AddCallbackForUrl(
1056 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1057 base::BindRepeating(
1058 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1059 base::Unretained(&cookie_changes)));
1060 this->DeliverChangeNotifications();
1061 ASSERT_EQ(0u, cookie_changes.size());
1062
1063 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1064 this->DeliverChangeNotifications();
1065 ASSERT_EQ(1u, cookie_changes.size());
1066 cookie_changes.clear();
1067
1068 // Replacing an existing cookie is actually a two-phase delete + set
1069 // operation, so we get an extra notification.
1070 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C"));
1071 this->DeliverChangeNotifications();
1072
1073 ASSERT_LE(1u, cookie_changes.size());
1074 EXPECT_EQ(this->http_www_foo_.url().host(),
1075 cookie_changes[0].cookie.Domain());
1076 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
1077 cookie_changes[0].cause));
1078 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1079 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1080
1081 ASSERT_LE(2u, cookie_changes.size());
1082 EXPECT_EQ(this->http_www_foo_.url().host(),
1083 cookie_changes[1].cookie.Domain());
1084 EXPECT_TRUE(
1085 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
1086 EXPECT_EQ("A", cookie_changes[1].cookie.Name());
1087 EXPECT_EQ("C", cookie_changes[1].cookie.Value());
1088
1089 EXPECT_EQ(2u, cookie_changes.size());
1090 }
1091
TYPED_TEST_P(CookieStoreChangeUrlTest,OverwriteFiltering)1092 TYPED_TEST_P(CookieStoreChangeUrlTest, OverwriteFiltering) {
1093 if (!TypeParam::supports_url_cookie_tracking)
1094 return;
1095
1096 CookieStore* cs = this->GetCookieStore();
1097 std::vector<CookieChangeInfo> cookie_changes;
1098 std::unique_ptr<CookieChangeSubscription> subscription =
1099 cs->GetChangeDispatcher().AddCallbackForUrl(
1100 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
1101 base::BindRepeating(
1102 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1103 base::Unretained(&cookie_changes)));
1104 this->DeliverChangeNotifications();
1105 ASSERT_EQ(0u, cookie_changes.size());
1106
1107 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/"));
1108 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D; path=/"));
1109 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F; path=/bar"));
1110 EXPECT_TRUE(
1111 this->SetCookie(cs, this->http_www_foo_.url(), "G=H; path=/foo/bar"));
1112 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "I=J; path=/foo"));
1113 EXPECT_TRUE(
1114 this->SetCookie(cs, this->http_www_foo_.url(), "K=L; domain=foo.com"));
1115 this->DeliverChangeNotifications();
1116 EXPECT_EQ(3u, cookie_changes.size());
1117 cookie_changes.clear();
1118
1119 // Replacing an existing cookie is actually a two-phase delete + set
1120 // operation, so we get two notifications per overwrite.
1121 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=b; path=/"));
1122 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=d; path=/"));
1123 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=f; path=/bar"));
1124 EXPECT_TRUE(
1125 this->SetCookie(cs, this->http_www_foo_.url(), "G=h; path=/foo/bar"));
1126 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "I=j; path=/foo"));
1127 EXPECT_TRUE(
1128 this->SetCookie(cs, this->http_www_foo_.url(), "K=l; domain=foo.com"));
1129 this->DeliverChangeNotifications();
1130
1131 ASSERT_LE(1u, cookie_changes.size());
1132 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1133 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1134 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
1135 EXPECT_EQ(this->http_www_foo_.url().host(),
1136 cookie_changes[0].cookie.Domain());
1137 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
1138 cookie_changes[0].cause));
1139
1140 ASSERT_LE(2u, cookie_changes.size());
1141 EXPECT_EQ("A", cookie_changes[1].cookie.Name());
1142 EXPECT_EQ("b", cookie_changes[1].cookie.Value());
1143 EXPECT_EQ("/", cookie_changes[1].cookie.Path());
1144 EXPECT_EQ(this->http_www_foo_.url().host(),
1145 cookie_changes[1].cookie.Domain());
1146 EXPECT_EQ(CookieChangeCause::INSERTED, cookie_changes[1].cause);
1147 EXPECT_TRUE(
1148 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
1149
1150 ASSERT_LE(3u, cookie_changes.size());
1151 EXPECT_EQ("I", cookie_changes[2].cookie.Name());
1152 EXPECT_EQ("J", cookie_changes[2].cookie.Value());
1153 EXPECT_EQ("/foo", cookie_changes[2].cookie.Path());
1154 EXPECT_EQ(this->http_www_foo_.url().host(),
1155 cookie_changes[2].cookie.Domain());
1156 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
1157 cookie_changes[2].cause));
1158
1159 ASSERT_LE(4u, cookie_changes.size());
1160 EXPECT_EQ("I", cookie_changes[3].cookie.Name());
1161 EXPECT_EQ("j", cookie_changes[3].cookie.Value());
1162 EXPECT_EQ("/foo", cookie_changes[3].cookie.Path());
1163 EXPECT_EQ(this->http_www_foo_.url().host(),
1164 cookie_changes[3].cookie.Domain());
1165 EXPECT_TRUE(
1166 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[3].cause));
1167
1168 ASSERT_LE(5u, cookie_changes.size());
1169 EXPECT_EQ("K", cookie_changes[4].cookie.Name());
1170 EXPECT_EQ("L", cookie_changes[4].cookie.Value());
1171 EXPECT_EQ("/", cookie_changes[4].cookie.Path());
1172 EXPECT_EQ(".foo.com", cookie_changes[4].cookie.Domain());
1173 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
1174 cookie_changes[4].cause));
1175
1176 ASSERT_LE(6u, cookie_changes.size());
1177 EXPECT_EQ("K", cookie_changes[5].cookie.Name());
1178 EXPECT_EQ("l", cookie_changes[5].cookie.Value());
1179 EXPECT_EQ("/", cookie_changes[5].cookie.Path());
1180 EXPECT_EQ(".foo.com", cookie_changes[5].cookie.Domain());
1181 EXPECT_TRUE(
1182 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[5].cause));
1183
1184 EXPECT_EQ(6u, cookie_changes.size());
1185 }
1186
TYPED_TEST_P(CookieStoreChangeUrlTest,OverwriteWithHttpOnly)1187 TYPED_TEST_P(CookieStoreChangeUrlTest, OverwriteWithHttpOnly) {
1188 if (!TypeParam::supports_url_cookie_tracking)
1189 return;
1190
1191 // Insert a cookie "A" for path "/foo".
1192 CookieStore* cs = this->GetCookieStore();
1193 std::vector<CookieChangeInfo> cookie_changes;
1194 std::unique_ptr<CookieChangeSubscription> subscription =
1195 cs->GetChangeDispatcher().AddCallbackForUrl(
1196 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
1197 base::BindRepeating(
1198 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1199 base::Unretained(&cookie_changes)));
1200 this->DeliverChangeNotifications();
1201 ASSERT_EQ(0u, cookie_changes.size());
1202
1203 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/foo"));
1204 this->DeliverChangeNotifications();
1205 ASSERT_EQ(1u, cookie_changes.size());
1206 EXPECT_TRUE(
1207 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
1208 EXPECT_EQ(this->http_www_foo_.url().host(),
1209 cookie_changes[0].cookie.Domain());
1210 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1211 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1212 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
1213 cookie_changes.clear();
1214
1215 // Insert a cookie "A" for path "/foo", that is httponly. This should
1216 // overwrite the non-http-only version.
1217 CookieOptions allow_httponly;
1218 allow_httponly.set_include_httponly();
1219 allow_httponly.set_same_site_cookie_context(
1220 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1221
1222 EXPECT_TRUE(this->CreateAndSetCookie(cs, this->http_www_foo_.url(),
1223 "A=C; path=/foo; httponly",
1224 allow_httponly));
1225 this->DeliverChangeNotifications();
1226
1227 ASSERT_LE(1u, cookie_changes.size());
1228 EXPECT_EQ(this->http_www_foo_.url().host(),
1229 cookie_changes[0].cookie.Domain());
1230 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
1231 cookie_changes[0].cause));
1232 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1233 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1234 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
1235
1236 ASSERT_LE(2u, cookie_changes.size());
1237 EXPECT_EQ(this->http_www_foo_.url().host(),
1238 cookie_changes[1].cookie.Domain());
1239 EXPECT_TRUE(
1240 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
1241 EXPECT_EQ("A", cookie_changes[1].cookie.Name());
1242 EXPECT_EQ("C", cookie_changes[1].cookie.Value());
1243 EXPECT_TRUE(cookie_changes[1].cookie.IsHttpOnly());
1244
1245 EXPECT_EQ(2u, cookie_changes.size());
1246 }
1247
TYPED_TEST_P(CookieStoreChangeUrlTest,Deregister)1248 TYPED_TEST_P(CookieStoreChangeUrlTest, Deregister) {
1249 if (!TypeParam::supports_url_cookie_tracking)
1250 return;
1251
1252 CookieStore* cs = this->GetCookieStore();
1253
1254 std::vector<CookieChangeInfo> cookie_changes;
1255 std::unique_ptr<CookieChangeSubscription> subscription =
1256 cs->GetChangeDispatcher().AddCallbackForUrl(
1257 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1258 base::BindRepeating(
1259 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1260 base::Unretained(&cookie_changes)));
1261 this->DeliverChangeNotifications();
1262 ASSERT_EQ(0u, cookie_changes.size());
1263
1264 // Insert a cookie and make sure it is seen.
1265 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1266 this->DeliverChangeNotifications();
1267 ASSERT_EQ(1u, cookie_changes.size());
1268 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1269 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1270 cookie_changes.clear();
1271
1272 // De-register the subscription.
1273 subscription.reset();
1274
1275 // Insert a second cookie and make sure it's not visible.
1276 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1277 this->DeliverChangeNotifications();
1278
1279 EXPECT_EQ(0u, cookie_changes.size());
1280 }
1281
TYPED_TEST_P(CookieStoreChangeUrlTest,DeregisterMultiple)1282 TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterMultiple) {
1283 if (!TypeParam::supports_url_cookie_tracking ||
1284 !TypeParam::supports_multiple_tracking_callbacks)
1285 return;
1286
1287 CookieStore* cs = this->GetCookieStore();
1288
1289 // Register two subscriptions.
1290 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1291 std::unique_ptr<CookieChangeSubscription> subscription1 =
1292 cs->GetChangeDispatcher().AddCallbackForUrl(
1293 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1294 base::BindRepeating(
1295 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1296 base::Unretained(&cookie_changes_1)));
1297 std::unique_ptr<CookieChangeSubscription> subscription2 =
1298 cs->GetChangeDispatcher().AddCallbackForUrl(
1299 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1300 base::BindRepeating(
1301 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1302 base::Unretained(&cookie_changes_2)));
1303 this->DeliverChangeNotifications();
1304 ASSERT_EQ(0u, cookie_changes_1.size());
1305 ASSERT_EQ(0u, cookie_changes_2.size());
1306
1307 // Insert a cookie and make sure it's seen.
1308 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1309 this->DeliverChangeNotifications();
1310 ASSERT_EQ(1u, cookie_changes_1.size());
1311 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1312 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1313 cookie_changes_1.clear();
1314
1315 ASSERT_EQ(1u, cookie_changes_2.size());
1316 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
1317 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
1318 cookie_changes_2.clear();
1319
1320 // De-register the second registration.
1321 subscription2.reset();
1322
1323 // Insert a second cookie and make sure that it's only visible in one
1324 // change array.
1325 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1326 this->DeliverChangeNotifications();
1327 ASSERT_EQ(1u, cookie_changes_1.size());
1328 EXPECT_EQ("C", cookie_changes_1[0].cookie.Name());
1329 EXPECT_EQ("D", cookie_changes_1[0].cookie.Value());
1330
1331 EXPECT_EQ(0u, cookie_changes_2.size());
1332 }
1333
1334 // Confirm that a listener does not receive notifications for changes that
1335 // happened right before the subscription was established.
TYPED_TEST_P(CookieStoreChangeUrlTest,DispatchRace)1336 TYPED_TEST_P(CookieStoreChangeUrlTest, DispatchRace) {
1337 if (!TypeParam::supports_url_cookie_tracking)
1338 return;
1339
1340 CookieStore* cs = this->GetCookieStore();
1341
1342 // This cookie insertion should not be seen.
1343 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1344 // DeliverChangeNotifications() must NOT be called before the subscription is
1345 // established.
1346
1347 std::vector<CookieChangeInfo> cookie_changes;
1348 std::unique_ptr<CookieChangeSubscription> subscription =
1349 cs->GetChangeDispatcher().AddCallbackForUrl(
1350 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1351 base::BindRepeating(
1352 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1353 base::Unretained(&cookie_changes)));
1354
1355 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1356 this->DeliverChangeNotifications();
1357
1358 EXPECT_LE(1u, cookie_changes.size());
1359 EXPECT_EQ("C", cookie_changes[0].cookie.Name());
1360 EXPECT_EQ("D", cookie_changes[0].cookie.Value());
1361
1362 ASSERT_EQ(1u, cookie_changes.size());
1363 }
1364
1365 // Confirm that deregistering a subscription blocks the notification if the
1366 // deregistration happened after the change but before the notification was
1367 // received.
TYPED_TEST_P(CookieStoreChangeUrlTest,DeregisterRace)1368 TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterRace) {
1369 if (!TypeParam::supports_url_cookie_tracking)
1370 return;
1371
1372 CookieStore* cs = this->GetCookieStore();
1373
1374 std::vector<CookieChangeInfo> cookie_changes;
1375 std::unique_ptr<CookieChangeSubscription> subscription =
1376 cs->GetChangeDispatcher().AddCallbackForUrl(
1377 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1378 base::BindRepeating(
1379 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1380 base::Unretained(&cookie_changes)));
1381 this->DeliverChangeNotifications();
1382 ASSERT_EQ(0u, cookie_changes.size());
1383
1384 // Insert a cookie and make sure it's seen.
1385 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1386 this->DeliverChangeNotifications();
1387 ASSERT_EQ(1u, cookie_changes.size());
1388 EXPECT_EQ("A", cookie_changes[0].cookie.Name());
1389 EXPECT_EQ("B", cookie_changes[0].cookie.Value());
1390 cookie_changes.clear();
1391
1392 // Insert a cookie, confirm it is not seen, deregister the subscription, run
1393 // until idle, and confirm the cookie is still not seen.
1394 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1395
1396 // Note that by the API contract it's perfectly valid to have received the
1397 // notification immediately, i.e. synchronously with the cookie change. In
1398 // that case, there's nothing to test.
1399 if (1u == cookie_changes.size())
1400 return;
1401
1402 // A task was posted by the SetCookie() above, but has not yet arrived. If it
1403 // arrived before the subscription is destroyed, callback execution would be
1404 // valid. Destroy the subscription so as to lose the race and make sure the
1405 // task posted arrives after the subscription was destroyed.
1406 subscription.reset();
1407 this->DeliverChangeNotifications();
1408 ASSERT_EQ(0u, cookie_changes.size());
1409 }
1410
TYPED_TEST_P(CookieStoreChangeUrlTest,DeregisterRaceMultiple)1411 TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterRaceMultiple) {
1412 if (!TypeParam::supports_url_cookie_tracking ||
1413 !TypeParam::supports_multiple_tracking_callbacks)
1414 return;
1415
1416 CookieStore* cs = this->GetCookieStore();
1417
1418 // Register two subscriptions.
1419 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1420 std::unique_ptr<CookieChangeSubscription> subscription1 =
1421 cs->GetChangeDispatcher().AddCallbackForUrl(
1422 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1423 base::BindRepeating(
1424 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1425 base::Unretained(&cookie_changes_1)));
1426 std::unique_ptr<CookieChangeSubscription> subscription2 =
1427 cs->GetChangeDispatcher().AddCallbackForUrl(
1428 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1429 base::BindRepeating(
1430 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1431 base::Unretained(&cookie_changes_2)));
1432 this->DeliverChangeNotifications();
1433 ASSERT_EQ(0u, cookie_changes_1.size());
1434 ASSERT_EQ(0u, cookie_changes_2.size());
1435
1436 // Insert a cookie and make sure it's seen.
1437 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1438 this->DeliverChangeNotifications();
1439
1440 ASSERT_EQ(1u, cookie_changes_1.size());
1441 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1442 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1443 cookie_changes_1.clear();
1444
1445 ASSERT_EQ(1u, cookie_changes_2.size());
1446 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
1447 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
1448 cookie_changes_2.clear();
1449
1450 // Insert a cookie, confirm it is not seen, deregister a subscription, run
1451 // until idle, and confirm the cookie is still not seen.
1452 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1453
1454 // Note that by the API contract it's perfectly valid to have received the
1455 // notification immediately, i.e. synchronously with the cookie change. In
1456 // that case, there's nothing to test.
1457 if (1u == cookie_changes_2.size())
1458 return;
1459
1460 // A task was posted by the SetCookie() above, but has not yet arrived. If it
1461 // arrived before the subscription is destroyed, callback execution would be
1462 // valid. Destroy one of the subscriptions so as to lose the race and make
1463 // sure the task posted arrives after the subscription was destroyed.
1464 subscription2.reset();
1465 this->DeliverChangeNotifications();
1466 ASSERT_EQ(1u, cookie_changes_1.size());
1467 EXPECT_EQ("C", cookie_changes_1[0].cookie.Name());
1468 EXPECT_EQ("D", cookie_changes_1[0].cookie.Value());
1469
1470 // No late notification was received.
1471 ASSERT_EQ(0u, cookie_changes_2.size());
1472 }
1473
TYPED_TEST_P(CookieStoreChangeUrlTest,DifferentSubscriptionsDisjoint)1474 TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsDisjoint) {
1475 if (!TypeParam::supports_url_cookie_tracking)
1476 return;
1477
1478 CookieStore* cs = this->GetCookieStore();
1479
1480 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1481 std::unique_ptr<CookieChangeSubscription> subscription1 =
1482 cs->GetChangeDispatcher().AddCallbackForUrl(
1483 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1484 base::BindRepeating(
1485 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1486 base::Unretained(&cookie_changes_1)));
1487 std::unique_ptr<CookieChangeSubscription> subscription2 =
1488 cs->GetChangeDispatcher().AddCallbackForUrl(
1489 this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */,
1490 base::BindRepeating(
1491 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1492 base::Unretained(&cookie_changes_2)));
1493 this->DeliverChangeNotifications();
1494 ASSERT_EQ(0u, cookie_changes_1.size());
1495 ASSERT_EQ(0u, cookie_changes_2.size());
1496
1497 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1498 this->DeliverChangeNotifications();
1499 EXPECT_EQ(1u, cookie_changes_1.size());
1500 EXPECT_EQ(0u, cookie_changes_2.size());
1501
1502 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D"));
1503 this->DeliverChangeNotifications();
1504
1505 ASSERT_EQ(1u, cookie_changes_1.size());
1506 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1507 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1508 EXPECT_EQ(this->http_www_foo_.url().host(),
1509 cookie_changes_1[0].cookie.Domain());
1510
1511 ASSERT_EQ(1u, cookie_changes_2.size());
1512 EXPECT_EQ("C", cookie_changes_2[0].cookie.Name());
1513 EXPECT_EQ("D", cookie_changes_2[0].cookie.Value());
1514 EXPECT_EQ(this->http_bar_com_.url().host(),
1515 cookie_changes_2[0].cookie.Domain());
1516 }
1517
TYPED_TEST_P(CookieStoreChangeUrlTest,DifferentSubscriptionsDomains)1518 TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsDomains) {
1519 if (!TypeParam::supports_url_cookie_tracking)
1520 return;
1521
1522 CookieStore* cs = this->GetCookieStore();
1523
1524 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1525 std::unique_ptr<CookieChangeSubscription> subscription1 =
1526 cs->GetChangeDispatcher().AddCallbackForUrl(
1527 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1528 base::BindRepeating(
1529 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1530 base::Unretained(&cookie_changes_1)));
1531 std::unique_ptr<CookieChangeSubscription> subscription2 =
1532 cs->GetChangeDispatcher().AddCallbackForUrl(
1533 this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */,
1534 base::BindRepeating(
1535 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1536 base::Unretained(&cookie_changes_2)));
1537 this->DeliverChangeNotifications();
1538 ASSERT_EQ(0u, cookie_changes_1.size());
1539 ASSERT_EQ(0u, cookie_changes_2.size());
1540
1541 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1542 this->DeliverChangeNotifications();
1543 EXPECT_EQ(1u, cookie_changes_1.size());
1544 EXPECT_EQ(0u, cookie_changes_2.size());
1545
1546 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D"));
1547 this->DeliverChangeNotifications();
1548
1549 ASSERT_EQ(1u, cookie_changes_1.size());
1550 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1551 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1552 EXPECT_EQ(this->http_www_foo_.url().host(),
1553 cookie_changes_1[0].cookie.Domain());
1554
1555 ASSERT_EQ(1u, cookie_changes_2.size());
1556 EXPECT_EQ("C", cookie_changes_2[0].cookie.Name());
1557 EXPECT_EQ("D", cookie_changes_2[0].cookie.Value());
1558 EXPECT_EQ(this->http_bar_com_.url().host(),
1559 cookie_changes_2[0].cookie.Domain());
1560 }
1561
TYPED_TEST_P(CookieStoreChangeUrlTest,DifferentSubscriptionsPaths)1562 TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsPaths) {
1563 if (!TypeParam::supports_url_cookie_tracking)
1564 return;
1565
1566 CookieStore* cs = this->GetCookieStore();
1567
1568 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1569 std::unique_ptr<CookieChangeSubscription> subscription1 =
1570 cs->GetChangeDispatcher().AddCallbackForUrl(
1571 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1572 base::BindRepeating(
1573 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1574 base::Unretained(&cookie_changes_1)));
1575 std::unique_ptr<CookieChangeSubscription> subscription2 =
1576 cs->GetChangeDispatcher().AddCallbackForUrl(
1577 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
1578 base::BindRepeating(
1579 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1580 base::Unretained(&cookie_changes_2)));
1581 this->DeliverChangeNotifications();
1582 ASSERT_EQ(0u, cookie_changes_1.size());
1583 ASSERT_EQ(0u, cookie_changes_2.size());
1584
1585 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1586 this->DeliverChangeNotifications();
1587 EXPECT_EQ(1u, cookie_changes_1.size());
1588 EXPECT_EQ(1u, cookie_changes_2.size());
1589
1590 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D; path=/foo"));
1591 this->DeliverChangeNotifications();
1592
1593 ASSERT_EQ(1u, cookie_changes_1.size());
1594 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1595 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1596 EXPECT_EQ("/", cookie_changes_1[0].cookie.Path());
1597 EXPECT_EQ(this->http_www_foo_.url().host(),
1598 cookie_changes_1[0].cookie.Domain());
1599
1600 ASSERT_LE(1u, cookie_changes_2.size());
1601 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
1602 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
1603 EXPECT_EQ("/", cookie_changes_2[0].cookie.Path());
1604 EXPECT_EQ(this->http_www_foo_.url().host(),
1605 cookie_changes_2[0].cookie.Domain());
1606
1607 ASSERT_LE(2u, cookie_changes_2.size());
1608 EXPECT_EQ("C", cookie_changes_2[1].cookie.Name());
1609 EXPECT_EQ("D", cookie_changes_2[1].cookie.Value());
1610 EXPECT_EQ("/foo", cookie_changes_2[1].cookie.Path());
1611 EXPECT_EQ(this->http_www_foo_.url().host(),
1612 cookie_changes_2[1].cookie.Domain());
1613
1614 EXPECT_EQ(2u, cookie_changes_2.size());
1615 }
1616
TYPED_TEST_P(CookieStoreChangeUrlTest,DifferentSubscriptionsFiltering)1617 TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsFiltering) {
1618 if (!TypeParam::supports_url_cookie_tracking)
1619 return;
1620
1621 CookieStore* cs = this->GetCookieStore();
1622
1623 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1624 std::vector<CookieChangeInfo> cookie_changes_3;
1625 std::unique_ptr<CookieChangeSubscription> subscription1 =
1626 cs->GetChangeDispatcher().AddCallbackForUrl(
1627 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1628 base::BindRepeating(
1629 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1630 base::Unretained(&cookie_changes_1)));
1631 std::unique_ptr<CookieChangeSubscription> subscription2 =
1632 cs->GetChangeDispatcher().AddCallbackForUrl(
1633 this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */,
1634 base::BindRepeating(
1635 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1636 base::Unretained(&cookie_changes_2)));
1637 std::unique_ptr<CookieChangeSubscription> subscription3 =
1638 cs->GetChangeDispatcher().AddCallbackForUrl(
1639 this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */,
1640 base::BindRepeating(
1641 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1642 base::Unretained(&cookie_changes_3)));
1643 this->DeliverChangeNotifications();
1644 ASSERT_EQ(0u, cookie_changes_1.size());
1645 ASSERT_EQ(0u, cookie_changes_2.size());
1646 EXPECT_EQ(0u, cookie_changes_3.size());
1647
1648 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1649 this->DeliverChangeNotifications();
1650 EXPECT_EQ(1u, cookie_changes_1.size());
1651 EXPECT_EQ(0u, cookie_changes_2.size());
1652 EXPECT_EQ(1u, cookie_changes_3.size());
1653
1654 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "C=D"));
1655 this->DeliverChangeNotifications();
1656 EXPECT_EQ(1u, cookie_changes_1.size());
1657 EXPECT_EQ(1u, cookie_changes_2.size());
1658 EXPECT_EQ(1u, cookie_changes_3.size());
1659
1660 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "E=F; path=/foo"));
1661 this->DeliverChangeNotifications();
1662
1663 ASSERT_LE(1u, cookie_changes_1.size());
1664 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1665 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1666 EXPECT_EQ(this->http_www_foo_.url().host(),
1667 cookie_changes_1[0].cookie.Domain());
1668 EXPECT_EQ(1u, cookie_changes_1.size());
1669
1670 ASSERT_LE(1u, cookie_changes_2.size());
1671 EXPECT_EQ("C", cookie_changes_2[0].cookie.Name());
1672 EXPECT_EQ("D", cookie_changes_2[0].cookie.Value());
1673 EXPECT_EQ(this->http_bar_com_.url().host(),
1674 cookie_changes_2[0].cookie.Domain());
1675 EXPECT_EQ(1u, cookie_changes_2.size());
1676
1677 ASSERT_LE(1u, cookie_changes_3.size());
1678 EXPECT_EQ("A", cookie_changes_3[0].cookie.Name());
1679 EXPECT_EQ("B", cookie_changes_3[0].cookie.Value());
1680 EXPECT_EQ("/", cookie_changes_3[0].cookie.Path());
1681 EXPECT_EQ(this->http_www_foo_.url().host(),
1682 cookie_changes_3[0].cookie.Domain());
1683
1684 ASSERT_LE(2u, cookie_changes_3.size());
1685 EXPECT_EQ("E", cookie_changes_3[1].cookie.Name());
1686 EXPECT_EQ("F", cookie_changes_3[1].cookie.Value());
1687 EXPECT_EQ("/foo", cookie_changes_3[1].cookie.Path());
1688 EXPECT_EQ(this->http_www_foo_.url().host(),
1689 cookie_changes_3[1].cookie.Domain());
1690
1691 EXPECT_EQ(2u, cookie_changes_3.size());
1692 }
1693
TYPED_TEST_P(CookieStoreChangeUrlTest,MultipleSubscriptions)1694 TYPED_TEST_P(CookieStoreChangeUrlTest, MultipleSubscriptions) {
1695 if (!TypeParam::supports_url_cookie_tracking ||
1696 !TypeParam::supports_multiple_tracking_callbacks)
1697 return;
1698
1699 CookieStore* cs = this->GetCookieStore();
1700
1701 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
1702 std::unique_ptr<CookieChangeSubscription> subscription1 =
1703 cs->GetChangeDispatcher().AddCallbackForUrl(
1704 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1705 base::BindRepeating(
1706 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1707 base::Unretained(&cookie_changes_1)));
1708 std::unique_ptr<CookieChangeSubscription> subscription2 =
1709 cs->GetChangeDispatcher().AddCallbackForUrl(
1710 this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */,
1711 base::BindRepeating(
1712 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1713 base::Unretained(&cookie_changes_2)));
1714 this->DeliverChangeNotifications();
1715
1716 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1717 this->DeliverChangeNotifications();
1718
1719 ASSERT_EQ(1U, cookie_changes_1.size());
1720 EXPECT_EQ("A", cookie_changes_1[0].cookie.Name());
1721 EXPECT_EQ("B", cookie_changes_1[0].cookie.Value());
1722
1723 ASSERT_EQ(1U, cookie_changes_2.size());
1724 EXPECT_EQ("A", cookie_changes_2[0].cookie.Name());
1725 EXPECT_EQ("B", cookie_changes_2[0].cookie.Value());
1726 }
1727
TYPED_TEST_P(CookieStoreChangeUrlTest,ChangeIncludesCookieAccessSemantics)1728 TYPED_TEST_P(CookieStoreChangeUrlTest, ChangeIncludesCookieAccessSemantics) {
1729 if (!TypeParam::supports_url_cookie_tracking)
1730 return;
1731
1732 CookieStore* cs = this->GetCookieStore();
1733 // if !supports_cookie_access_semantics, the delegate will be stored but will
1734 // not be used.
1735 auto access_delegate = std::make_unique<TestCookieAccessDelegate>();
1736 access_delegate->SetExpectationForCookieDomain("domain1.test",
1737 CookieAccessSemantics::LEGACY);
1738 cs->SetCookieAccessDelegate(std::move(access_delegate));
1739
1740 std::vector<CookieChangeInfo> cookie_changes;
1741 std::unique_ptr<CookieChangeSubscription> subscription =
1742 cs->GetChangeDispatcher().AddCallbackForUrl(
1743 GURL("http://domain1.test"), std::nullopt /* cookie_partition_key */,
1744 base::BindRepeating(
1745 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1746 base::Unretained(&cookie_changes)));
1747
1748 this->CreateAndSetCookie(cs, GURL("http://domain1.test"), "cookie=1",
1749 CookieOptions::MakeAllInclusive());
1750 this->DeliverChangeNotifications();
1751
1752 ASSERT_EQ(1u, cookie_changes.size());
1753
1754 EXPECT_EQ("domain1.test", cookie_changes[0].cookie.Domain());
1755 EXPECT_TRUE(this->IsExpectedAccessSemantics(
1756 CookieAccessSemantics::LEGACY,
1757 cookie_changes[0].access_result.access_semantics));
1758 }
1759
TYPED_TEST_P(CookieStoreChangeUrlTest,PartitionedCookies)1760 TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies) {
1761 if (!TypeParam::supports_url_cookie_tracking ||
1762 !TypeParam::supports_partitioned_cookies)
1763 return;
1764
1765 CookieStore* cs = this->GetCookieStore();
1766 std::vector<CookieChangeInfo> cookie_changes;
1767 std::unique_ptr<CookieChangeSubscription> subscription =
1768 cs->GetChangeDispatcher().AddCallbackForUrl(
1769 GURL("https://www.example.com/"),
1770 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")),
1771 base::BindRepeating(
1772 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1773 base::Unretained(&cookie_changes)));
1774
1775 // Unpartitioned cookie
1776 this->CreateAndSetCookie(cs, GURL("https://www.example.com/"),
1777 "__Host-a=1; Secure; Path=/",
1778 CookieOptions::MakeAllInclusive());
1779 // Partitioned cookie with the same partition key
1780 this->CreateAndSetCookie(
1781 cs, GURL("https://www.example.com/"),
1782 "__Host-b=2; Secure; Path=/; Partitioned",
1783 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
1784 std::nullopt /* system_time */,
1785 CookiePartitionKey::FromURLForTesting(GURL("https://sub.foo.com")));
1786 // Partitioned cookie with a different partition key
1787 this->CreateAndSetCookie(
1788 cs, GURL("https://www.example.com"),
1789 "__Host-c=3; Secure; Path=/; Partitioned",
1790 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
1791 std::nullopt /* system_time */,
1792 CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com")));
1793 this->DeliverChangeNotifications();
1794
1795 ASSERT_EQ(2u, cookie_changes.size());
1796 EXPECT_FALSE(cookie_changes[0].cookie.IsPartitioned());
1797 EXPECT_EQ("__Host-a", cookie_changes[0].cookie.Name());
1798 EXPECT_TRUE(cookie_changes[1].cookie.IsPartitioned());
1799 EXPECT_EQ(CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")),
1800 cookie_changes[1].cookie.PartitionKey().value());
1801 EXPECT_EQ("__Host-b", cookie_changes[1].cookie.Name());
1802
1803 // Test that when the partition key parameter is nullopt that all Partitioned
1804 // cookies do not emit events.
1805
1806 std::vector<CookieChangeInfo> other_cookie_changes;
1807 std::unique_ptr<CookieChangeSubscription> other_subscription =
1808 cs->GetChangeDispatcher().AddCallbackForUrl(
1809 GURL("https://www.example.com/"),
1810 std::nullopt /* cookie_partition_key */,
1811 base::BindRepeating(
1812 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1813 base::Unretained(&other_cookie_changes)));
1814 // Update Max-Age: None -> 7200
1815 this->CreateAndSetCookie(
1816 cs, GURL("https://www.example.com"),
1817 "__Host-b=2; Secure; Path=/; Partitioned; Max-Age=7200",
1818 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
1819 std::nullopt /* system_time */,
1820 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
1821 this->DeliverChangeNotifications();
1822 ASSERT_EQ(0u, other_cookie_changes.size());
1823 // Check that the other listener was invoked.
1824 ASSERT_LT(2u, cookie_changes.size());
1825 }
1826
TYPED_TEST_P(CookieStoreChangeUrlTest,PartitionedCookies_WithNonce)1827 TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies_WithNonce) {
1828 if (!TypeParam::supports_named_cookie_tracking ||
1829 !TypeParam::supports_partitioned_cookies) {
1830 return;
1831 }
1832
1833 CookieStore* cs = this->GetCookieStore();
1834 base::UnguessableToken nonce = base::UnguessableToken::Create();
1835
1836 std::vector<CookieChangeInfo> cookie_changes;
1837 std::unique_ptr<CookieChangeSubscription> subscription =
1838 cs->GetChangeDispatcher().AddCallbackForUrl(
1839 GURL("https://www.example.com"),
1840 CookiePartitionKey::FromURLForTesting(
1841 GURL("https://www.foo.com"),
1842 CookiePartitionKey::AncestorChainBit::kCrossSite, nonce),
1843 base::BindRepeating(
1844 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1845 base::Unretained(&cookie_changes)));
1846
1847 // Should not see changes to an unpartitioned cookie.
1848 this->CreateAndSetCookie(cs, GURL("https://www.example.com"),
1849 "__Host-a=1; Secure; Path=/",
1850 CookieOptions::MakeAllInclusive());
1851 this->DeliverChangeNotifications();
1852 ASSERT_EQ(0u, cookie_changes.size());
1853
1854 // Set partitioned cookie without nonce. Should not see the change.
1855 this->CreateAndSetCookie(
1856 cs, GURL("https://www.example.com"),
1857 "__Host-a=2; Secure; Path=/; Partitioned",
1858 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
1859 std::nullopt /* system_time */,
1860 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
1861 this->DeliverChangeNotifications();
1862 ASSERT_EQ(0u, cookie_changes.size());
1863
1864 // Set partitioned cookie with nonce.
1865 this->CreateAndSetCookie(
1866 cs, GURL("https://www.example.com"),
1867 "__Host-a=3; Secure; Path=/; Partitioned",
1868 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
1869 std::nullopt /* system_time */,
1870 CookiePartitionKey::FromURLForTesting(
1871 GURL("https://www.foo.com"),
1872 CookiePartitionKey::AncestorChainBit::kCrossSite, nonce));
1873 this->DeliverChangeNotifications();
1874 ASSERT_EQ(1u, cookie_changes.size());
1875 }
1876
TYPED_TEST_P(CookieStoreChangeNamedTest,NoCookie)1877 TYPED_TEST_P(CookieStoreChangeNamedTest, NoCookie) {
1878 if (!TypeParam::supports_named_cookie_tracking)
1879 return;
1880
1881 CookieStore* cs = this->GetCookieStore();
1882 std::vector<CookieChangeInfo> cookie_changes;
1883 std::unique_ptr<CookieChangeSubscription> subscription =
1884 cs->GetChangeDispatcher().AddCallbackForCookie(
1885 this->http_www_foo_.url(), "abc",
1886 std::nullopt /* cookie_partition_key */,
1887 base::BindRepeating(
1888 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1889 base::Unretained(&cookie_changes)));
1890 this->DeliverChangeNotifications();
1891 EXPECT_EQ(0u, cookie_changes.size());
1892 }
1893
TYPED_TEST_P(CookieStoreChangeNamedTest,InitialCookie)1894 TYPED_TEST_P(CookieStoreChangeNamedTest, InitialCookie) {
1895 if (!TypeParam::supports_named_cookie_tracking)
1896 return;
1897
1898 CookieStore* cs = this->GetCookieStore();
1899 std::vector<CookieChangeInfo> cookie_changes;
1900 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def");
1901 this->DeliverChangeNotifications();
1902 std::unique_ptr<CookieChangeSubscription> subscription =
1903 cs->GetChangeDispatcher().AddCallbackForCookie(
1904 this->http_www_foo_.url(), "abc",
1905 std::nullopt /* cookie_partition_key */,
1906 base::BindRepeating(
1907 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1908 base::Unretained(&cookie_changes)));
1909 this->DeliverChangeNotifications();
1910 EXPECT_EQ(0u, cookie_changes.size());
1911 }
1912
TYPED_TEST_P(CookieStoreChangeNamedTest,InsertOne)1913 TYPED_TEST_P(CookieStoreChangeNamedTest, InsertOne) {
1914 if (!TypeParam::supports_named_cookie_tracking)
1915 return;
1916
1917 CookieStore* cs = this->GetCookieStore();
1918 std::vector<CookieChangeInfo> cookie_changes;
1919 std::unique_ptr<CookieChangeSubscription> subscription =
1920 cs->GetChangeDispatcher().AddCallbackForCookie(
1921 this->http_www_foo_.url(), "abc",
1922 std::nullopt /* cookie_partition_key */,
1923 base::BindRepeating(
1924 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1925 base::Unretained(&cookie_changes)));
1926 this->DeliverChangeNotifications();
1927 ASSERT_EQ(0u, cookie_changes.size());
1928
1929 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
1930 this->DeliverChangeNotifications();
1931 ASSERT_EQ(1u, cookie_changes.size());
1932
1933 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
1934 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
1935 EXPECT_EQ(this->http_www_foo_.url().host(),
1936 cookie_changes[0].cookie.Domain());
1937 EXPECT_TRUE(
1938 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
1939 }
1940
TYPED_TEST_P(CookieStoreChangeNamedTest,InsertTwo)1941 TYPED_TEST_P(CookieStoreChangeNamedTest, InsertTwo) {
1942 if (!TypeParam::supports_named_cookie_tracking)
1943 return;
1944
1945 CookieStore* cs = this->GetCookieStore();
1946 std::vector<CookieChangeInfo> cookie_changes;
1947 std::unique_ptr<CookieChangeSubscription> subscription =
1948 cs->GetChangeDispatcher().AddCallbackForCookie(
1949 this->www_foo_foo_.url(), "abc",
1950 std::nullopt /* cookie_partition_key */,
1951 base::BindRepeating(
1952 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1953 base::Unretained(&cookie_changes)));
1954 this->DeliverChangeNotifications();
1955 ASSERT_EQ(0u, cookie_changes.size());
1956
1957 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
1958 EXPECT_TRUE(
1959 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/foo"));
1960 this->DeliverChangeNotifications();
1961
1962 ASSERT_LE(1u, cookie_changes.size());
1963 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
1964 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
1965 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
1966 EXPECT_EQ(this->http_www_foo_.url().host(),
1967 cookie_changes[0].cookie.Domain());
1968 EXPECT_TRUE(
1969 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
1970
1971 ASSERT_LE(2u, cookie_changes.size());
1972 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
1973 EXPECT_EQ("hij", cookie_changes[1].cookie.Value());
1974 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
1975 EXPECT_EQ(this->http_www_foo_.url().host(),
1976 cookie_changes[1].cookie.Domain());
1977 EXPECT_TRUE(
1978 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
1979
1980 EXPECT_EQ(2u, cookie_changes.size());
1981 }
1982
TYPED_TEST_P(CookieStoreChangeNamedTest,InsertFiltering)1983 TYPED_TEST_P(CookieStoreChangeNamedTest, InsertFiltering) {
1984 if (!TypeParam::supports_named_cookie_tracking)
1985 return;
1986
1987 CookieStore* cs = this->GetCookieStore();
1988 std::vector<CookieChangeInfo> cookie_changes;
1989 std::unique_ptr<CookieChangeSubscription> subscription =
1990 cs->GetChangeDispatcher().AddCallbackForCookie(
1991 this->www_foo_foo_.url(), "abc",
1992 std::nullopt /* cookie_partition_key */,
1993 base::BindRepeating(
1994 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
1995 base::Unretained(&cookie_changes)));
1996 this->DeliverChangeNotifications();
1997 ASSERT_EQ(0u, cookie_changes.size());
1998
1999 EXPECT_TRUE(
2000 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/"));
2001 EXPECT_TRUE(
2002 this->SetCookie(cs, this->http_bar_com_.url(), "abc=ghi; path=/"));
2003 EXPECT_TRUE(
2004 this->SetCookie(cs, this->http_www_foo_.url(), "abc=jkl; path=/bar"));
2005 EXPECT_TRUE(
2006 this->SetCookie(cs, this->http_www_foo_.url(), "abc=mno; path=/foo/bar"));
2007 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx"));
2008 EXPECT_TRUE(
2009 this->SetCookie(cs, this->http_www_foo_.url(), "abc=pqr; path=/foo"));
2010 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2011 "abc=stu; domain=foo.com"));
2012 this->DeliverChangeNotifications();
2013
2014 ASSERT_LE(1u, cookie_changes.size());
2015 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2016 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2017 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
2018 EXPECT_EQ(this->http_www_foo_.url().host(),
2019 cookie_changes[0].cookie.Domain());
2020 EXPECT_TRUE(
2021 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
2022
2023 ASSERT_LE(2u, cookie_changes.size());
2024 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2025 EXPECT_EQ("pqr", cookie_changes[1].cookie.Value());
2026 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
2027 EXPECT_EQ(this->http_www_foo_.url().host(),
2028 cookie_changes[1].cookie.Domain());
2029 EXPECT_TRUE(
2030 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
2031
2032 ASSERT_LE(3u, cookie_changes.size());
2033 EXPECT_EQ("abc", cookie_changes[2].cookie.Name());
2034 EXPECT_EQ("stu", cookie_changes[2].cookie.Value());
2035 EXPECT_EQ("/", cookie_changes[2].cookie.Path());
2036 EXPECT_EQ(".foo.com", cookie_changes[2].cookie.Domain());
2037 EXPECT_TRUE(
2038 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[2].cause));
2039
2040 EXPECT_EQ(3u, cookie_changes.size());
2041 }
2042
TYPED_TEST_P(CookieStoreChangeNamedTest,DeleteOne)2043 TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteOne) {
2044 if (!TypeParam::supports_named_cookie_tracking)
2045 return;
2046
2047 CookieStore* cs = this->GetCookieStore();
2048 std::vector<CookieChangeInfo> cookie_changes;
2049 std::unique_ptr<CookieChangeSubscription> subscription =
2050 cs->GetChangeDispatcher().AddCallbackForCookie(
2051 this->http_www_foo_.url(), "abc",
2052 std::nullopt /* cookie_partition_key */,
2053 base::BindRepeating(
2054 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2055 base::Unretained(&cookie_changes)));
2056 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2057 this->DeliverChangeNotifications();
2058 EXPECT_EQ(1u, cookie_changes.size());
2059 cookie_changes.clear();
2060
2061 EXPECT_TRUE(
2062 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "abc"));
2063 this->DeliverChangeNotifications();
2064
2065 ASSERT_EQ(1u, cookie_changes.size());
2066 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2067 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2068 EXPECT_EQ(this->http_www_foo_.url().host(),
2069 cookie_changes[0].cookie.Domain());
2070 EXPECT_TRUE(
2071 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
2072 }
2073
TYPED_TEST_P(CookieStoreChangeNamedTest,DeleteTwo)2074 TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteTwo) {
2075 if (!TypeParam::supports_named_cookie_tracking)
2076 return;
2077
2078 CookieStore* cs = this->GetCookieStore();
2079 std::vector<CookieChangeInfo> cookie_changes;
2080 std::unique_ptr<CookieChangeSubscription> subscription =
2081 cs->GetChangeDispatcher().AddCallbackForCookie(
2082 this->www_foo_foo_.url(), "abc",
2083 std::nullopt /* cookie_partition_key */,
2084 base::BindRepeating(
2085 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2086 base::Unretained(&cookie_changes)));
2087 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2088 EXPECT_TRUE(
2089 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/foo"));
2090 this->DeliverChangeNotifications();
2091 EXPECT_EQ(2u, cookie_changes.size());
2092 cookie_changes.clear();
2093
2094 EXPECT_TRUE(this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(),
2095 "abc", "/"));
2096 EXPECT_TRUE(this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(),
2097 "abc", "/foo"));
2098 this->DeliverChangeNotifications();
2099
2100 ASSERT_LE(1u, cookie_changes.size());
2101 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2102 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2103 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
2104 EXPECT_EQ(this->http_www_foo_.url().host(),
2105 cookie_changes[0].cookie.Domain());
2106 EXPECT_TRUE(
2107 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
2108
2109 ASSERT_EQ(2u, cookie_changes.size());
2110 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2111 EXPECT_EQ("hij", cookie_changes[1].cookie.Value());
2112 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
2113 EXPECT_EQ(this->http_www_foo_.url().host(),
2114 cookie_changes[1].cookie.Domain());
2115 EXPECT_TRUE(
2116 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[1].cause));
2117 }
2118
TYPED_TEST_P(CookieStoreChangeNamedTest,DeleteFiltering)2119 TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteFiltering) {
2120 if (!TypeParam::supports_named_cookie_tracking)
2121 return;
2122
2123 CookieStore* cs = this->GetCookieStore();
2124 std::vector<CookieChangeInfo> cookie_changes;
2125 std::unique_ptr<CookieChangeSubscription> subscription =
2126 cs->GetChangeDispatcher().AddCallbackForCookie(
2127 this->www_foo_foo_.url(), "abc",
2128 std::nullopt /* cookie_partition_key */,
2129 base::BindRepeating(
2130 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2131 base::Unretained(&cookie_changes)));
2132 EXPECT_TRUE(
2133 this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx; path=/"));
2134 EXPECT_TRUE(
2135 this->SetCookie(cs, this->http_bar_com_.url(), "abc=def; path=/"));
2136 EXPECT_TRUE(
2137 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/foo/bar"));
2138 EXPECT_TRUE(
2139 this->SetCookie(cs, this->http_www_foo_.url(), "abc=mno; path=/foo"));
2140 EXPECT_TRUE(
2141 this->SetCookie(cs, this->http_www_foo_.url(), "abc=pqr; path=/"));
2142 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2143 "abc=stu; domain=foo.com"));
2144 this->DeliverChangeNotifications();
2145 EXPECT_EQ(3u, cookie_changes.size());
2146 cookie_changes.clear();
2147
2148 EXPECT_TRUE(
2149 this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(), "xyz"));
2150 EXPECT_TRUE(
2151 this->FindAndDeleteCookie(cs, this->http_bar_com_.url().host(), "abc"));
2152 EXPECT_TRUE(this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(),
2153 "abc", "/foo/bar"));
2154 EXPECT_TRUE(this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(),
2155 "abc", "/foo"));
2156 EXPECT_TRUE(this->FindAndDeleteCookie(cs, this->http_www_foo_.url().host(),
2157 "abc", "/"));
2158 EXPECT_TRUE(this->FindAndDeleteCookie(cs, ".foo.com", "abc", "/"));
2159 this->DeliverChangeNotifications();
2160
2161 ASSERT_LE(1u, cookie_changes.size());
2162 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2163 EXPECT_EQ("mno", cookie_changes[0].cookie.Value());
2164 EXPECT_EQ("/foo", cookie_changes[0].cookie.Path());
2165 EXPECT_EQ(this->http_www_foo_.url().host(),
2166 cookie_changes[0].cookie.Domain());
2167 EXPECT_TRUE(
2168 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[0].cause));
2169
2170 ASSERT_LE(2u, cookie_changes.size());
2171 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2172 EXPECT_EQ("pqr", cookie_changes[1].cookie.Value());
2173 EXPECT_EQ("/", cookie_changes[1].cookie.Path());
2174 EXPECT_EQ(this->http_www_foo_.url().host(),
2175 cookie_changes[1].cookie.Domain());
2176 EXPECT_TRUE(
2177 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[1].cause));
2178
2179 ASSERT_LE(3u, cookie_changes.size());
2180 EXPECT_EQ("abc", cookie_changes[2].cookie.Name());
2181 EXPECT_EQ("stu", cookie_changes[2].cookie.Value());
2182 EXPECT_EQ("/", cookie_changes[2].cookie.Path());
2183 EXPECT_EQ(".foo.com", cookie_changes[2].cookie.Domain());
2184 EXPECT_TRUE(
2185 this->MatchesCause(CookieChangeCause::EXPLICIT, cookie_changes[2].cause));
2186
2187 EXPECT_EQ(3u, cookie_changes.size());
2188 }
2189
TYPED_TEST_P(CookieStoreChangeNamedTest,Overwrite)2190 TYPED_TEST_P(CookieStoreChangeNamedTest, Overwrite) {
2191 if (!TypeParam::supports_named_cookie_tracking)
2192 return;
2193
2194 CookieStore* cs = this->GetCookieStore();
2195 std::vector<CookieChangeInfo> cookie_changes;
2196 std::unique_ptr<CookieChangeSubscription> subscription =
2197 cs->GetChangeDispatcher().AddCallbackForCookie(
2198 this->http_www_foo_.url(), "abc",
2199 std::nullopt /* cookie_partition_key */,
2200 base::BindRepeating(
2201 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2202 base::Unretained(&cookie_changes)));
2203 this->DeliverChangeNotifications();
2204 ASSERT_EQ(0u, cookie_changes.size());
2205
2206 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2207 this->DeliverChangeNotifications();
2208 EXPECT_EQ(1u, cookie_changes.size());
2209 cookie_changes.clear();
2210
2211 // Replacing an existing cookie is actually a two-phase delete + set
2212 // operation, so we get an extra notification.
2213 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=ghi"));
2214 this->DeliverChangeNotifications();
2215
2216 EXPECT_LE(1u, cookie_changes.size());
2217 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2218 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2219 EXPECT_EQ(this->http_www_foo_.url().host(),
2220 cookie_changes[0].cookie.Domain());
2221 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
2222 cookie_changes[0].cause));
2223
2224 EXPECT_LE(2u, cookie_changes.size());
2225 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2226 EXPECT_EQ("ghi", cookie_changes[1].cookie.Value());
2227 EXPECT_EQ(this->http_www_foo_.url().host(),
2228 cookie_changes[1].cookie.Domain());
2229 EXPECT_TRUE(
2230 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
2231
2232 EXPECT_EQ(2u, cookie_changes.size());
2233 }
2234
TYPED_TEST_P(CookieStoreChangeNamedTest,OverwriteFiltering)2235 TYPED_TEST_P(CookieStoreChangeNamedTest, OverwriteFiltering) {
2236 if (!TypeParam::supports_named_cookie_tracking)
2237 return;
2238
2239 CookieStore* cs = this->GetCookieStore();
2240 std::vector<CookieChangeInfo> cookie_changes;
2241 std::unique_ptr<CookieChangeSubscription> subscription =
2242 cs->GetChangeDispatcher().AddCallbackForCookie(
2243 this->www_foo_foo_.url(), "abc",
2244 std::nullopt /* cookie_partition_key */,
2245 base::BindRepeating(
2246 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2247 base::Unretained(&cookie_changes)));
2248 this->DeliverChangeNotifications();
2249 ASSERT_EQ(0u, cookie_changes.size());
2250
2251 EXPECT_TRUE(
2252 this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx1; path=/"));
2253 EXPECT_TRUE(
2254 this->SetCookie(cs, this->http_bar_com_.url(), "abc=def1; path=/"));
2255 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2256 "abc=hij1; path=/foo/bar"));
2257 EXPECT_TRUE(
2258 this->SetCookie(cs, this->http_www_foo_.url(), "abc=mno1; path=/foo"));
2259 EXPECT_TRUE(
2260 this->SetCookie(cs, this->http_www_foo_.url(), "abc=pqr1; path=/"));
2261 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2262 "abc=stu1; domain=foo.com"));
2263 this->DeliverChangeNotifications();
2264 EXPECT_EQ(3u, cookie_changes.size());
2265 cookie_changes.clear();
2266
2267 // Replacing an existing cookie is actually a two-phase delete + set
2268 // operation, so we get two notifications per overwrite.
2269 EXPECT_TRUE(
2270 this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx2; path=/"));
2271 EXPECT_TRUE(
2272 this->SetCookie(cs, this->http_bar_com_.url(), "abc=def2; path=/"));
2273 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2274 "abc=hij2; path=/foo/bar"));
2275 EXPECT_TRUE(
2276 this->SetCookie(cs, this->http_www_foo_.url(), "abc=mno2; path=/foo"));
2277 EXPECT_TRUE(
2278 this->SetCookie(cs, this->http_www_foo_.url(), "abc=pqr2; path=/"));
2279 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
2280 "abc=stu2; domain=foo.com"));
2281 this->DeliverChangeNotifications();
2282
2283 ASSERT_LE(1u, cookie_changes.size());
2284 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2285 EXPECT_EQ("mno1", cookie_changes[0].cookie.Value());
2286 EXPECT_EQ("/foo", cookie_changes[0].cookie.Path());
2287 EXPECT_EQ(this->http_www_foo_.url().host(),
2288 cookie_changes[0].cookie.Domain());
2289 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
2290 cookie_changes[0].cause));
2291
2292 ASSERT_LE(2u, cookie_changes.size());
2293 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2294 EXPECT_EQ("mno2", cookie_changes[1].cookie.Value());
2295 EXPECT_EQ("/foo", cookie_changes[1].cookie.Path());
2296 EXPECT_EQ(this->http_www_foo_.url().host(),
2297 cookie_changes[1].cookie.Domain());
2298 EXPECT_TRUE(
2299 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
2300
2301 ASSERT_LE(3u, cookie_changes.size());
2302 EXPECT_EQ("abc", cookie_changes[2].cookie.Name());
2303 EXPECT_EQ("pqr1", cookie_changes[2].cookie.Value());
2304 EXPECT_EQ("/", cookie_changes[2].cookie.Path());
2305 EXPECT_EQ(this->http_www_foo_.url().host(),
2306 cookie_changes[2].cookie.Domain());
2307 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
2308 cookie_changes[2].cause));
2309
2310 ASSERT_LE(4u, cookie_changes.size());
2311 EXPECT_EQ("abc", cookie_changes[3].cookie.Name());
2312 EXPECT_EQ("pqr2", cookie_changes[3].cookie.Value());
2313 EXPECT_EQ("/", cookie_changes[3].cookie.Path());
2314 EXPECT_EQ(this->http_www_foo_.url().host(),
2315 cookie_changes[3].cookie.Domain());
2316 EXPECT_TRUE(
2317 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[3].cause));
2318
2319 ASSERT_LE(5u, cookie_changes.size());
2320 EXPECT_EQ("abc", cookie_changes[4].cookie.Name());
2321 EXPECT_EQ("stu1", cookie_changes[4].cookie.Value());
2322 EXPECT_EQ("/", cookie_changes[4].cookie.Path());
2323 EXPECT_EQ(".foo.com", cookie_changes[4].cookie.Domain());
2324 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
2325 cookie_changes[4].cause));
2326
2327 ASSERT_LE(6u, cookie_changes.size());
2328 EXPECT_EQ("abc", cookie_changes[5].cookie.Name());
2329 EXPECT_EQ("stu2", cookie_changes[5].cookie.Value());
2330 EXPECT_EQ("/", cookie_changes[5].cookie.Path());
2331 EXPECT_EQ(".foo.com", cookie_changes[5].cookie.Domain());
2332 EXPECT_TRUE(
2333 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[5].cause));
2334
2335 EXPECT_EQ(6u, cookie_changes.size());
2336 }
2337
TYPED_TEST_P(CookieStoreChangeNamedTest,OverwriteWithHttpOnly)2338 TYPED_TEST_P(CookieStoreChangeNamedTest, OverwriteWithHttpOnly) {
2339 if (!TypeParam::supports_named_cookie_tracking)
2340 return;
2341
2342 // Insert a cookie "abc" for path "/foo".
2343 CookieStore* cs = this->GetCookieStore();
2344 std::vector<CookieChangeInfo> cookie_changes;
2345 std::unique_ptr<CookieChangeSubscription> subscription =
2346 cs->GetChangeDispatcher().AddCallbackForCookie(
2347 this->www_foo_foo_.url(), "abc",
2348 std::nullopt /* cookie_partition_key */,
2349 base::BindRepeating(
2350 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2351 base::Unretained(&cookie_changes)));
2352 this->DeliverChangeNotifications();
2353 ASSERT_EQ(0u, cookie_changes.size());
2354
2355 EXPECT_TRUE(
2356 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2357 this->DeliverChangeNotifications();
2358 ASSERT_EQ(1u, cookie_changes.size());
2359 EXPECT_TRUE(
2360 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[0].cause));
2361 EXPECT_EQ(this->http_www_foo_.url().host(),
2362 cookie_changes[0].cookie.Domain());
2363 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2364 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2365 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
2366 cookie_changes.clear();
2367
2368 // Insert a cookie "a" for path "/foo", that is httponly. This should
2369 // overwrite the non-http-only version.
2370 CookieOptions allow_httponly;
2371 allow_httponly.set_include_httponly();
2372 allow_httponly.set_same_site_cookie_context(
2373 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
2374
2375 EXPECT_TRUE(this->CreateAndSetCookie(cs, this->http_www_foo_.url(),
2376 "abc=hij; path=/foo; httponly",
2377 allow_httponly));
2378 this->DeliverChangeNotifications();
2379
2380 ASSERT_LE(1u, cookie_changes.size());
2381 EXPECT_EQ(this->http_www_foo_.url().host(),
2382 cookie_changes[0].cookie.Domain());
2383 EXPECT_TRUE(this->MatchesCause(CookieChangeCause::OVERWRITE,
2384 cookie_changes[0].cause));
2385 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2386 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2387 EXPECT_FALSE(cookie_changes[0].cookie.IsHttpOnly());
2388
2389 ASSERT_LE(2u, cookie_changes.size());
2390 EXPECT_EQ(this->http_www_foo_.url().host(),
2391 cookie_changes[1].cookie.Domain());
2392 EXPECT_TRUE(
2393 this->MatchesCause(CookieChangeCause::INSERTED, cookie_changes[1].cause));
2394 EXPECT_EQ("abc", cookie_changes[1].cookie.Name());
2395 EXPECT_EQ("hij", cookie_changes[1].cookie.Value());
2396 EXPECT_TRUE(cookie_changes[1].cookie.IsHttpOnly());
2397
2398 EXPECT_EQ(2u, cookie_changes.size());
2399 }
2400
TYPED_TEST_P(CookieStoreChangeNamedTest,Deregister)2401 TYPED_TEST_P(CookieStoreChangeNamedTest, Deregister) {
2402 if (!TypeParam::supports_named_cookie_tracking)
2403 return;
2404
2405 CookieStore* cs = this->GetCookieStore();
2406
2407 std::vector<CookieChangeInfo> cookie_changes;
2408 std::unique_ptr<CookieChangeSubscription> subscription =
2409 cs->GetChangeDispatcher().AddCallbackForCookie(
2410 this->www_foo_foo_.url(), "abc",
2411 std::nullopt /* cookie_partition_key */,
2412 base::BindRepeating(
2413 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2414 base::Unretained(&cookie_changes)));
2415 this->DeliverChangeNotifications();
2416 ASSERT_EQ(0u, cookie_changes.size());
2417
2418 // Insert a cookie and make sure it is seen.
2419 EXPECT_TRUE(
2420 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2421 this->DeliverChangeNotifications();
2422 ASSERT_EQ(1u, cookie_changes.size());
2423 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2424 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2425 EXPECT_EQ("/foo", cookie_changes[0].cookie.Path());
2426 cookie_changes.clear();
2427
2428 // De-register the subscription.
2429 subscription.reset();
2430
2431 // Insert a second cookie and make sure it's not visible.
2432 EXPECT_TRUE(
2433 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/"));
2434 this->DeliverChangeNotifications();
2435
2436 EXPECT_EQ(0u, cookie_changes.size());
2437 }
2438
TYPED_TEST_P(CookieStoreChangeNamedTest,DeregisterMultiple)2439 TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterMultiple) {
2440 if (!TypeParam::supports_named_cookie_tracking ||
2441 !TypeParam::supports_multiple_tracking_callbacks)
2442 return;
2443
2444 CookieStore* cs = this->GetCookieStore();
2445
2446 // Register two subscriptions.
2447 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2448 std::unique_ptr<CookieChangeSubscription> subscription1 =
2449 cs->GetChangeDispatcher().AddCallbackForCookie(
2450 this->www_foo_foo_.url(), "abc",
2451 std::nullopt /* cookie_partition_key */,
2452 base::BindRepeating(
2453 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2454 base::Unretained(&cookie_changes_1)));
2455 std::unique_ptr<CookieChangeSubscription> subscription2 =
2456 cs->GetChangeDispatcher().AddCallbackForCookie(
2457 this->www_foo_foo_.url(), "abc",
2458 std::nullopt /* cookie_partition_key */,
2459 base::BindRepeating(
2460 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2461 base::Unretained(&cookie_changes_2)));
2462 this->DeliverChangeNotifications();
2463 ASSERT_EQ(0u, cookie_changes_1.size());
2464 ASSERT_EQ(0u, cookie_changes_2.size());
2465
2466 // Insert a cookie and make sure it's seen.
2467 EXPECT_TRUE(
2468 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2469 this->DeliverChangeNotifications();
2470 ASSERT_EQ(1u, cookie_changes_1.size());
2471 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2472 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2473 EXPECT_EQ("/foo", cookie_changes_1[0].cookie.Path());
2474 cookie_changes_1.clear();
2475
2476 ASSERT_EQ(1u, cookie_changes_2.size());
2477 EXPECT_EQ("abc", cookie_changes_2[0].cookie.Name());
2478 EXPECT_EQ("def", cookie_changes_2[0].cookie.Value());
2479 EXPECT_EQ("/foo", cookie_changes_2[0].cookie.Path());
2480 cookie_changes_2.clear();
2481
2482 // De-register the second registration.
2483 subscription2.reset();
2484
2485 // Insert a second cookie and make sure that it's only visible in one
2486 // change array.
2487 EXPECT_TRUE(
2488 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/"));
2489 this->DeliverChangeNotifications();
2490 ASSERT_EQ(1u, cookie_changes_1.size());
2491 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2492 EXPECT_EQ("hij", cookie_changes_1[0].cookie.Value());
2493 EXPECT_EQ("/", cookie_changes_1[0].cookie.Path());
2494
2495 EXPECT_EQ(0u, cookie_changes_2.size());
2496 }
2497
2498 // Confirm that a listener does not receive notifications for changes that
2499 // happened right before the subscription was established.
TYPED_TEST_P(CookieStoreChangeNamedTest,DispatchRace)2500 TYPED_TEST_P(CookieStoreChangeNamedTest, DispatchRace) {
2501 if (!TypeParam::supports_named_cookie_tracking)
2502 return;
2503
2504 CookieStore* cs = this->GetCookieStore();
2505
2506 // This cookie insertion should not be seen.
2507 EXPECT_TRUE(
2508 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2509 // DeliverChangeNotifications() must NOT be called before the subscription is
2510 // established.
2511
2512 std::vector<CookieChangeInfo> cookie_changes;
2513 std::unique_ptr<CookieChangeSubscription> subscription =
2514 cs->GetChangeDispatcher().AddCallbackForCookie(
2515 this->www_foo_foo_.url(), "abc",
2516 std::nullopt /* cookie_partition_key */,
2517 base::BindRepeating(
2518 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2519 base::Unretained(&cookie_changes)));
2520
2521 EXPECT_TRUE(
2522 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/"));
2523 this->DeliverChangeNotifications();
2524
2525 EXPECT_LE(1u, cookie_changes.size());
2526 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2527 EXPECT_EQ("hij", cookie_changes[0].cookie.Value());
2528 EXPECT_EQ("/", cookie_changes[0].cookie.Path());
2529
2530 ASSERT_EQ(1u, cookie_changes.size());
2531 }
2532
2533 // Confirm that deregistering a subscription blocks the notification if the
2534 // deregistration happened after the change but before the notification was
2535 // received.
TYPED_TEST_P(CookieStoreChangeNamedTest,DeregisterRace)2536 TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterRace) {
2537 if (!TypeParam::supports_named_cookie_tracking)
2538 return;
2539
2540 CookieStore* cs = this->GetCookieStore();
2541
2542 std::vector<CookieChangeInfo> cookie_changes;
2543 std::unique_ptr<CookieChangeSubscription> subscription =
2544 cs->GetChangeDispatcher().AddCallbackForCookie(
2545 this->www_foo_foo_.url(), "abc",
2546 std::nullopt /* cookie_partition_key */,
2547 base::BindRepeating(
2548 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2549 base::Unretained(&cookie_changes)));
2550 this->DeliverChangeNotifications();
2551 ASSERT_EQ(0u, cookie_changes.size());
2552
2553 // Insert a cookie and make sure it's seen.
2554 EXPECT_TRUE(
2555 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2556 this->DeliverChangeNotifications();
2557 ASSERT_EQ(1u, cookie_changes.size());
2558 EXPECT_EQ("abc", cookie_changes[0].cookie.Name());
2559 EXPECT_EQ("def", cookie_changes[0].cookie.Value());
2560 EXPECT_EQ("/foo", cookie_changes[0].cookie.Path());
2561 cookie_changes.clear();
2562
2563 // Insert a cookie, confirm it is not seen, deregister the subscription, run
2564 // until idle, and confirm the cookie is still not seen.
2565 EXPECT_TRUE(
2566 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/"));
2567
2568 // Note that by the API contract it's perfectly valid to have received the
2569 // notification immediately, i.e. synchronously with the cookie change. In
2570 // that case, there's nothing to test.
2571 if (1u == cookie_changes.size())
2572 return;
2573
2574 // A task was posted by the SetCookie() above, but has not yet arrived. If it
2575 // arrived before the subscription is destroyed, callback execution would be
2576 // valid. Destroy the subscription so as to lose the race and make sure the
2577 // task posted arrives after the subscription was destroyed.
2578 subscription.reset();
2579 this->DeliverChangeNotifications();
2580 ASSERT_EQ(0u, cookie_changes.size());
2581 }
2582
TYPED_TEST_P(CookieStoreChangeNamedTest,DeregisterRaceMultiple)2583 TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterRaceMultiple) {
2584 if (!TypeParam::supports_named_cookie_tracking ||
2585 !TypeParam::supports_multiple_tracking_callbacks)
2586 return;
2587
2588 CookieStore* cs = this->GetCookieStore();
2589
2590 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2591 std::unique_ptr<CookieChangeSubscription> subscription1 =
2592 cs->GetChangeDispatcher().AddCallbackForCookie(
2593 this->www_foo_foo_.url(), "abc",
2594 std::nullopt /* cookie_partition_key */,
2595 base::BindRepeating(
2596 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2597 base::Unretained(&cookie_changes_1)));
2598 std::unique_ptr<CookieChangeSubscription> subscription2 =
2599 cs->GetChangeDispatcher().AddCallbackForCookie(
2600 this->www_foo_foo_.url(), "abc",
2601 std::nullopt /* cookie_partition_key */,
2602 base::BindRepeating(
2603 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2604 base::Unretained(&cookie_changes_2)));
2605 this->DeliverChangeNotifications();
2606 ASSERT_EQ(0u, cookie_changes_1.size());
2607 ASSERT_EQ(0u, cookie_changes_2.size());
2608
2609 // Insert a cookie and make sure it's seen.
2610 EXPECT_TRUE(
2611 this->SetCookie(cs, this->http_www_foo_.url(), "abc=def; path=/foo"));
2612 this->DeliverChangeNotifications();
2613
2614 ASSERT_EQ(1u, cookie_changes_1.size());
2615 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2616 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2617 EXPECT_EQ("/foo", cookie_changes_1[0].cookie.Path());
2618 cookie_changes_1.clear();
2619
2620 ASSERT_EQ(1u, cookie_changes_2.size());
2621 EXPECT_EQ("abc", cookie_changes_2[0].cookie.Name());
2622 EXPECT_EQ("def", cookie_changes_2[0].cookie.Value());
2623 EXPECT_EQ("/foo", cookie_changes_2[0].cookie.Path());
2624 cookie_changes_2.clear();
2625
2626 // Insert a cookie, confirm it is not seen, deregister a subscription, run
2627 // until idle, and confirm the cookie is still not seen.
2628 EXPECT_TRUE(
2629 this->SetCookie(cs, this->http_www_foo_.url(), "abc=hij; path=/"));
2630
2631 // Note that by the API contract it's perfectly valid to have received the
2632 // notification immediately, i.e. synchronously with the cookie change. In
2633 // that case, there's nothing to test.
2634 if (1u == cookie_changes_2.size())
2635 return;
2636
2637 // A task was posted by the SetCookie() above, but has not yet arrived. If it
2638 // arrived before the subscription is destroyed, callback execution would be
2639 // valid. Destroy one of the subscriptions so as to lose the race and make
2640 // sure the task posted arrives after the subscription was destroyed.
2641 subscription2.reset();
2642 this->DeliverChangeNotifications();
2643 ASSERT_EQ(1u, cookie_changes_1.size());
2644 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2645 EXPECT_EQ("hij", cookie_changes_1[0].cookie.Value());
2646 EXPECT_EQ("/", cookie_changes_1[0].cookie.Path());
2647
2648 // No late notification was received.
2649 ASSERT_EQ(0u, cookie_changes_2.size());
2650 }
2651
TYPED_TEST_P(CookieStoreChangeNamedTest,DifferentSubscriptionsDisjoint)2652 TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsDisjoint) {
2653 if (!TypeParam::supports_named_cookie_tracking)
2654 return;
2655
2656 CookieStore* cs = this->GetCookieStore();
2657
2658 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2659 std::unique_ptr<CookieChangeSubscription> subscription1 =
2660 cs->GetChangeDispatcher().AddCallbackForCookie(
2661 this->http_www_foo_.url(), "abc",
2662 std::nullopt /* cookie_partition_key */,
2663 base::BindRepeating(
2664 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2665 base::Unretained(&cookie_changes_1)));
2666 std::unique_ptr<CookieChangeSubscription> subscription2 =
2667 cs->GetChangeDispatcher().AddCallbackForCookie(
2668 this->http_bar_com_.url(), "ghi",
2669 std::nullopt /* cookie_partition_key */,
2670 base::BindRepeating(
2671 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2672 base::Unretained(&cookie_changes_2)));
2673 this->DeliverChangeNotifications();
2674 ASSERT_EQ(0u, cookie_changes_1.size());
2675 ASSERT_EQ(0u, cookie_changes_2.size());
2676
2677 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2678 this->DeliverChangeNotifications();
2679 EXPECT_EQ(1u, cookie_changes_1.size());
2680 EXPECT_EQ(0u, cookie_changes_2.size());
2681
2682 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "ghi=jkl"));
2683 this->DeliverChangeNotifications();
2684
2685 ASSERT_EQ(1u, cookie_changes_1.size());
2686 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2687 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2688 EXPECT_EQ(this->http_www_foo_.url().host(),
2689 cookie_changes_1[0].cookie.Domain());
2690
2691 ASSERT_EQ(1u, cookie_changes_2.size());
2692 EXPECT_EQ("ghi", cookie_changes_2[0].cookie.Name());
2693 EXPECT_EQ("jkl", cookie_changes_2[0].cookie.Value());
2694 EXPECT_EQ(this->http_bar_com_.url().host(),
2695 cookie_changes_2[0].cookie.Domain());
2696 }
2697
TYPED_TEST_P(CookieStoreChangeNamedTest,DifferentSubscriptionsDomains)2698 TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsDomains) {
2699 if (!TypeParam::supports_named_cookie_tracking)
2700 return;
2701
2702 CookieStore* cs = this->GetCookieStore();
2703
2704 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2705 std::unique_ptr<CookieChangeSubscription> subscription1 =
2706 cs->GetChangeDispatcher().AddCallbackForCookie(
2707 this->http_www_foo_.url(), "abc",
2708 std::nullopt /* cookie_partition_key */,
2709 base::BindRepeating(
2710 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2711 base::Unretained(&cookie_changes_1)));
2712 std::unique_ptr<CookieChangeSubscription> subscription2 =
2713 cs->GetChangeDispatcher().AddCallbackForCookie(
2714 this->http_bar_com_.url(), "abc",
2715 std::nullopt /* cookie_partition_key */,
2716 base::BindRepeating(
2717 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2718 base::Unretained(&cookie_changes_2)));
2719 this->DeliverChangeNotifications();
2720 ASSERT_EQ(0u, cookie_changes_1.size());
2721 ASSERT_EQ(0u, cookie_changes_2.size());
2722
2723 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2724 this->DeliverChangeNotifications();
2725 EXPECT_EQ(1u, cookie_changes_1.size());
2726 EXPECT_EQ(0u, cookie_changes_2.size());
2727
2728 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "abc=ghi"));
2729 this->DeliverChangeNotifications();
2730
2731 ASSERT_EQ(1u, cookie_changes_1.size());
2732 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2733 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2734 EXPECT_EQ(this->http_www_foo_.url().host(),
2735 cookie_changes_1[0].cookie.Domain());
2736
2737 ASSERT_EQ(1u, cookie_changes_2.size());
2738 EXPECT_EQ("abc", cookie_changes_2[0].cookie.Name());
2739 EXPECT_EQ("ghi", cookie_changes_2[0].cookie.Value());
2740 EXPECT_EQ(this->http_bar_com_.url().host(),
2741 cookie_changes_2[0].cookie.Domain());
2742 }
2743
TYPED_TEST_P(CookieStoreChangeNamedTest,DifferentSubscriptionsNames)2744 TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsNames) {
2745 if (!TypeParam::supports_named_cookie_tracking)
2746 return;
2747
2748 CookieStore* cs = this->GetCookieStore();
2749
2750 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2751 std::unique_ptr<CookieChangeSubscription> subscription1 =
2752 cs->GetChangeDispatcher().AddCallbackForCookie(
2753 this->http_www_foo_.url(), "abc",
2754 std::nullopt /* cookie_partition_key */,
2755 base::BindRepeating(
2756 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2757 base::Unretained(&cookie_changes_1)));
2758 std::unique_ptr<CookieChangeSubscription> subscription2 =
2759 cs->GetChangeDispatcher().AddCallbackForCookie(
2760 this->http_www_foo_.url(), "ghi",
2761 std::nullopt /* cookie_partition_key */,
2762 base::BindRepeating(
2763 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2764 base::Unretained(&cookie_changes_2)));
2765 this->DeliverChangeNotifications();
2766 ASSERT_EQ(0u, cookie_changes_1.size());
2767 ASSERT_EQ(0u, cookie_changes_2.size());
2768
2769 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2770 this->DeliverChangeNotifications();
2771 EXPECT_EQ(1u, cookie_changes_1.size());
2772 EXPECT_EQ(0u, cookie_changes_2.size());
2773
2774 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "ghi=jkl"));
2775 this->DeliverChangeNotifications();
2776
2777 ASSERT_EQ(1u, cookie_changes_1.size());
2778 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2779 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2780 EXPECT_EQ(this->http_www_foo_.url().host(),
2781 cookie_changes_1[0].cookie.Domain());
2782
2783 ASSERT_EQ(1u, cookie_changes_2.size());
2784 EXPECT_EQ("ghi", cookie_changes_2[0].cookie.Name());
2785 EXPECT_EQ("jkl", cookie_changes_2[0].cookie.Value());
2786 EXPECT_EQ(this->http_www_foo_.url().host(),
2787 cookie_changes_2[0].cookie.Domain());
2788 }
2789
TYPED_TEST_P(CookieStoreChangeNamedTest,DifferentSubscriptionsPaths)2790 TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsPaths) {
2791 if (!TypeParam::supports_named_cookie_tracking)
2792 return;
2793
2794 CookieStore* cs = this->GetCookieStore();
2795
2796 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2797 std::unique_ptr<CookieChangeSubscription> subscription1 =
2798 cs->GetChangeDispatcher().AddCallbackForCookie(
2799 this->http_www_foo_.url(), "abc",
2800 std::nullopt /* cookie_partition_key */,
2801 base::BindRepeating(
2802 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2803 base::Unretained(&cookie_changes_1)));
2804 std::unique_ptr<CookieChangeSubscription> subscription2 =
2805 cs->GetChangeDispatcher().AddCallbackForCookie(
2806 this->www_foo_foo_.url(), "abc",
2807 std::nullopt /* cookie_partition_key */,
2808 base::BindRepeating(
2809 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2810 base::Unretained(&cookie_changes_2)));
2811 this->DeliverChangeNotifications();
2812 ASSERT_EQ(0u, cookie_changes_1.size());
2813 ASSERT_EQ(0u, cookie_changes_2.size());
2814
2815 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2816 this->DeliverChangeNotifications();
2817 EXPECT_EQ(1u, cookie_changes_1.size());
2818 EXPECT_EQ(1u, cookie_changes_2.size());
2819
2820 EXPECT_TRUE(
2821 this->SetCookie(cs, this->http_www_foo_.url(), "abc=ghi; path=/foo"));
2822 this->DeliverChangeNotifications();
2823
2824 ASSERT_EQ(1u, cookie_changes_1.size());
2825 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2826 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2827 EXPECT_EQ("/", cookie_changes_1[0].cookie.Path());
2828 EXPECT_EQ(this->http_www_foo_.url().host(),
2829 cookie_changes_1[0].cookie.Domain());
2830
2831 ASSERT_LE(1u, cookie_changes_2.size());
2832 EXPECT_EQ("abc", cookie_changes_2[0].cookie.Name());
2833 EXPECT_EQ("def", cookie_changes_2[0].cookie.Value());
2834 EXPECT_EQ("/", cookie_changes_2[0].cookie.Path());
2835 EXPECT_EQ(this->http_www_foo_.url().host(),
2836 cookie_changes_2[0].cookie.Domain());
2837
2838 ASSERT_LE(2u, cookie_changes_2.size());
2839 EXPECT_EQ("abc", cookie_changes_2[1].cookie.Name());
2840 EXPECT_EQ("ghi", cookie_changes_2[1].cookie.Value());
2841 EXPECT_EQ("/foo", cookie_changes_2[1].cookie.Path());
2842 EXPECT_EQ(this->http_www_foo_.url().host(),
2843 cookie_changes_2[1].cookie.Domain());
2844
2845 EXPECT_EQ(2u, cookie_changes_2.size());
2846 }
2847
TYPED_TEST_P(CookieStoreChangeNamedTest,DifferentSubscriptionsFiltering)2848 TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsFiltering) {
2849 if (!TypeParam::supports_named_cookie_tracking)
2850 return;
2851
2852 CookieStore* cs = this->GetCookieStore();
2853
2854 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2855 std::vector<CookieChangeInfo> cookie_changes_3, cookie_changes_4;
2856 std::unique_ptr<CookieChangeSubscription> subscription1 =
2857 cs->GetChangeDispatcher().AddCallbackForCookie(
2858 this->http_www_foo_.url(), "abc",
2859 std::nullopt /* cookie_partition_key */,
2860 base::BindRepeating(
2861 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2862 base::Unretained(&cookie_changes_1)));
2863 std::unique_ptr<CookieChangeSubscription> subscription2 =
2864 cs->GetChangeDispatcher().AddCallbackForCookie(
2865 this->http_www_foo_.url(), "hij",
2866 std::nullopt /* cookie_partition_key */,
2867 base::BindRepeating(
2868 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2869 base::Unretained(&cookie_changes_2)));
2870 std::unique_ptr<CookieChangeSubscription> subscription3 =
2871 cs->GetChangeDispatcher().AddCallbackForCookie(
2872 this->http_bar_com_.url(), "abc",
2873 std::nullopt /* cookie_partition_key */,
2874 base::BindRepeating(
2875 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2876 base::Unretained(&cookie_changes_3)));
2877 std::unique_ptr<CookieChangeSubscription> subscription4 =
2878 cs->GetChangeDispatcher().AddCallbackForCookie(
2879 this->www_foo_foo_.url(), "abc",
2880 std::nullopt /* cookie_partition_key */,
2881 base::BindRepeating(
2882 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2883 base::Unretained(&cookie_changes_4)));
2884 this->DeliverChangeNotifications();
2885 ASSERT_EQ(0u, cookie_changes_1.size());
2886 ASSERT_EQ(0u, cookie_changes_2.size());
2887 EXPECT_EQ(0u, cookie_changes_3.size());
2888 EXPECT_EQ(0u, cookie_changes_4.size());
2889
2890 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2891 this->DeliverChangeNotifications();
2892 EXPECT_EQ(1u, cookie_changes_1.size());
2893 EXPECT_EQ(0u, cookie_changes_2.size());
2894 EXPECT_EQ(0u, cookie_changes_3.size());
2895 EXPECT_EQ(1u, cookie_changes_4.size());
2896
2897 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx"));
2898 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "hij=mno"));
2899 this->DeliverChangeNotifications();
2900 EXPECT_EQ(1u, cookie_changes_1.size());
2901 EXPECT_EQ(1u, cookie_changes_2.size());
2902 EXPECT_EQ(0u, cookie_changes_3.size());
2903 EXPECT_EQ(1u, cookie_changes_4.size());
2904
2905 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "hij=pqr"));
2906 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "xyz=zyx"));
2907 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "abc=stu"));
2908 this->DeliverChangeNotifications();
2909 EXPECT_EQ(1u, cookie_changes_1.size());
2910 EXPECT_EQ(1u, cookie_changes_2.size());
2911 EXPECT_EQ(1u, cookie_changes_3.size());
2912 EXPECT_EQ(1u, cookie_changes_4.size());
2913
2914 EXPECT_TRUE(
2915 this->SetCookie(cs, this->http_www_foo_.url(), "abc=vwx; path=/foo"));
2916 this->DeliverChangeNotifications();
2917
2918 ASSERT_LE(1u, cookie_changes_1.size());
2919 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2920 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2921 EXPECT_EQ(this->http_www_foo_.url().host(),
2922 cookie_changes_1[0].cookie.Domain());
2923 EXPECT_EQ(1u, cookie_changes_1.size());
2924
2925 ASSERT_LE(1u, cookie_changes_2.size());
2926 EXPECT_EQ("hij", cookie_changes_2[0].cookie.Name());
2927 EXPECT_EQ("mno", cookie_changes_2[0].cookie.Value());
2928 EXPECT_EQ(this->http_www_foo_.url().host(),
2929 cookie_changes_2[0].cookie.Domain());
2930 EXPECT_EQ(1u, cookie_changes_2.size());
2931
2932 ASSERT_LE(1u, cookie_changes_3.size());
2933 EXPECT_EQ("abc", cookie_changes_3[0].cookie.Name());
2934 EXPECT_EQ("stu", cookie_changes_3[0].cookie.Value());
2935 EXPECT_EQ(this->http_bar_com_.url().host(),
2936 cookie_changes_3[0].cookie.Domain());
2937 EXPECT_EQ(1u, cookie_changes_3.size());
2938
2939 ASSERT_LE(1u, cookie_changes_4.size());
2940 EXPECT_EQ("abc", cookie_changes_4[0].cookie.Name());
2941 EXPECT_EQ("def", cookie_changes_4[0].cookie.Value());
2942 EXPECT_EQ("/", cookie_changes_4[0].cookie.Path());
2943 EXPECT_EQ(this->http_www_foo_.url().host(),
2944 cookie_changes_4[0].cookie.Domain());
2945
2946 ASSERT_LE(2u, cookie_changes_4.size());
2947 EXPECT_EQ("abc", cookie_changes_4[1].cookie.Name());
2948 EXPECT_EQ("vwx", cookie_changes_4[1].cookie.Value());
2949 EXPECT_EQ("/foo", cookie_changes_4[1].cookie.Path());
2950 EXPECT_EQ(this->http_www_foo_.url().host(),
2951 cookie_changes_4[1].cookie.Domain());
2952
2953 EXPECT_EQ(2u, cookie_changes_4.size());
2954 }
2955
TYPED_TEST_P(CookieStoreChangeNamedTest,MultipleSubscriptions)2956 TYPED_TEST_P(CookieStoreChangeNamedTest, MultipleSubscriptions) {
2957 if (!TypeParam::supports_named_cookie_tracking ||
2958 !TypeParam::supports_multiple_tracking_callbacks)
2959 return;
2960
2961 CookieStore* cs = this->GetCookieStore();
2962
2963 std::vector<CookieChangeInfo> cookie_changes_1, cookie_changes_2;
2964 std::unique_ptr<CookieChangeSubscription> subscription1 =
2965 cs->GetChangeDispatcher().AddCallbackForCookie(
2966 this->http_www_foo_.url(), "abc",
2967 std::nullopt /* cookie_partition_key */,
2968 base::BindRepeating(
2969 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2970 base::Unretained(&cookie_changes_1)));
2971 std::unique_ptr<CookieChangeSubscription> subscription2 =
2972 cs->GetChangeDispatcher().AddCallbackForCookie(
2973 this->http_www_foo_.url(), "abc",
2974 std::nullopt /* cookie_partition_key */,
2975 base::BindRepeating(
2976 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
2977 base::Unretained(&cookie_changes_2)));
2978 this->DeliverChangeNotifications();
2979
2980 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "xyz=zyx"));
2981 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "abc=def"));
2982 this->DeliverChangeNotifications();
2983
2984 ASSERT_EQ(1U, cookie_changes_1.size());
2985 EXPECT_EQ("abc", cookie_changes_1[0].cookie.Name());
2986 EXPECT_EQ("def", cookie_changes_1[0].cookie.Value());
2987 cookie_changes_1.clear();
2988
2989 ASSERT_EQ(1U, cookie_changes_2.size());
2990 EXPECT_EQ("abc", cookie_changes_2[0].cookie.Name());
2991 EXPECT_EQ("def", cookie_changes_2[0].cookie.Value());
2992 cookie_changes_2.clear();
2993 }
2994
TYPED_TEST_P(CookieStoreChangeNamedTest,SubscriptionOutlivesStore)2995 TYPED_TEST_P(CookieStoreChangeNamedTest, SubscriptionOutlivesStore) {
2996 if (!TypeParam::supports_named_cookie_tracking)
2997 return;
2998
2999 std::vector<CookieChangeInfo> cookie_changes;
3000 std::unique_ptr<CookieChangeSubscription> subscription =
3001 this->GetCookieStore()->GetChangeDispatcher().AddCallbackForCookie(
3002 this->http_www_foo_.url(), "abc",
3003 std::nullopt /* cookie_partition_key */,
3004 base::BindRepeating(
3005 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
3006 base::Unretained(&cookie_changes)));
3007 this->ResetCookieStore();
3008
3009 // |subscription| outlives cookie_store - crash should not happen.
3010 subscription.reset();
3011 }
3012
TYPED_TEST_P(CookieStoreChangeNamedTest,ChangeIncludesCookieAccessSemantics)3013 TYPED_TEST_P(CookieStoreChangeNamedTest, ChangeIncludesCookieAccessSemantics) {
3014 if (!TypeParam::supports_named_cookie_tracking)
3015 return;
3016
3017 CookieStore* cs = this->GetCookieStore();
3018 // if !supports_cookie_access_semantics, the delegate will be stored but will
3019 // not be used.
3020 auto access_delegate = std::make_unique<TestCookieAccessDelegate>();
3021 access_delegate->SetExpectationForCookieDomain("domain1.test",
3022 CookieAccessSemantics::LEGACY);
3023 cs->SetCookieAccessDelegate(std::move(access_delegate));
3024
3025 std::vector<CookieChangeInfo> cookie_changes;
3026 std::unique_ptr<CookieChangeSubscription> subscription =
3027 cs->GetChangeDispatcher().AddCallbackForCookie(
3028 GURL("http://domain1.test"), "cookie",
3029 std::nullopt /* cookie_partition_key */,
3030 base::BindRepeating(
3031 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
3032 base::Unretained(&cookie_changes)));
3033
3034 this->CreateAndSetCookie(cs, GURL("http://domain1.test"), "cookie=1",
3035 CookieOptions::MakeAllInclusive());
3036 this->DeliverChangeNotifications();
3037
3038 ASSERT_EQ(1u, cookie_changes.size());
3039 EXPECT_EQ("domain1.test", cookie_changes[0].cookie.Domain());
3040 EXPECT_EQ("cookie", cookie_changes[0].cookie.Name());
3041 EXPECT_TRUE(this->IsExpectedAccessSemantics(
3042 CookieAccessSemantics::LEGACY,
3043 cookie_changes[0].access_result.access_semantics));
3044 }
3045
TYPED_TEST_P(CookieStoreChangeNamedTest,PartitionedCookies)3046 TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies) {
3047 if (!TypeParam::supports_named_cookie_tracking ||
3048 !TypeParam::supports_partitioned_cookies)
3049 return;
3050
3051 CookieStore* cs = this->GetCookieStore();
3052 std::vector<CookieChangeInfo> cookie_changes;
3053 std::unique_ptr<CookieChangeSubscription> subscription =
3054 cs->GetChangeDispatcher().AddCallbackForCookie(
3055 GURL("https://www.example.com"), "__Host-a",
3056 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")),
3057 base::BindRepeating(
3058 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
3059 base::Unretained(&cookie_changes)));
3060
3061 // Unpartitioned cookie
3062 this->CreateAndSetCookie(cs, GURL("https://www.example.com"),
3063 "__Host-a=1; Secure; Path=/",
3064 CookieOptions::MakeAllInclusive());
3065 // Partitioned cookie with the same partition key
3066 this->CreateAndSetCookie(
3067 cs, GURL("https://www.example.com"),
3068 "__Host-a=2; Secure; Path=/; Partitioned",
3069 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
3070 std::nullopt /* system_time */,
3071 CookiePartitionKey::FromURLForTesting(GURL("https://sub.foo.com")));
3072 // Partitioned cookie with a different partition key
3073 this->CreateAndSetCookie(
3074 cs, GURL("https://www.example.com"),
3075 "__Host-a=3; Secure; Path=/; Partitioned",
3076 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
3077 std::nullopt /* system_time */,
3078 CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com")));
3079 this->DeliverChangeNotifications();
3080
3081 ASSERT_EQ(2u, cookie_changes.size());
3082 EXPECT_FALSE(cookie_changes[0].cookie.IsPartitioned());
3083 EXPECT_EQ("1", cookie_changes[0].cookie.Value());
3084 EXPECT_TRUE(cookie_changes[1].cookie.IsPartitioned());
3085 EXPECT_EQ(CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")),
3086 cookie_changes[1].cookie.PartitionKey().value());
3087 EXPECT_EQ("2", cookie_changes[1].cookie.Value());
3088
3089 // Test that when the partition key parameter is nullopt that all Partitioned
3090 // cookies do not emit events.
3091 std::vector<CookieChangeInfo> other_cookie_changes;
3092 std::unique_ptr<CookieChangeSubscription> other_subscription =
3093 cs->GetChangeDispatcher().AddCallbackForCookie(
3094 GURL("https://www.example.com"), "__Host-a",
3095 std::nullopt /* cookie_partition_key */,
3096 base::BindRepeating(
3097 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
3098 base::Unretained(&other_cookie_changes)));
3099 // Update Max-Age: None -> 7200
3100 this->CreateAndSetCookie(
3101 cs, GURL("https://www.example.com"),
3102 "__Host-a=2; Secure; Path=/; Partitioned; Max-Age=7200",
3103 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
3104 std::nullopt /* system_time */,
3105 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
3106 this->DeliverChangeNotifications();
3107 ASSERT_EQ(0u, other_cookie_changes.size());
3108 // Check that the other listener was invoked.
3109 ASSERT_LT(2u, cookie_changes.size());
3110 }
3111
TYPED_TEST_P(CookieStoreChangeNamedTest,PartitionedCookies_WithNonce)3112 TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies_WithNonce) {
3113 if (!TypeParam::supports_named_cookie_tracking ||
3114 !TypeParam::supports_partitioned_cookies) {
3115 return;
3116 }
3117
3118 CookieStore* cs = this->GetCookieStore();
3119 base::UnguessableToken nonce = base::UnguessableToken::Create();
3120
3121 std::vector<CookieChangeInfo> cookie_changes;
3122 std::unique_ptr<CookieChangeSubscription> subscription =
3123 cs->GetChangeDispatcher().AddCallbackForCookie(
3124 GURL("https://www.example.com"), "__Host-a",
3125 CookiePartitionKey::FromURLForTesting(
3126 GURL("https://www.foo.com"),
3127 CookiePartitionKey::AncestorChainBit::kCrossSite, nonce),
3128 base::BindRepeating(
3129 &CookieStoreChangeTestBase<TypeParam>::OnCookieChange,
3130 base::Unretained(&cookie_changes)));
3131
3132 // Should not see changes to an unpartitioned cookie.
3133 this->CreateAndSetCookie(cs, GURL("https://www.example.com"),
3134 "__Host-a=1; Secure; Path=/",
3135 CookieOptions::MakeAllInclusive());
3136 this->DeliverChangeNotifications();
3137 ASSERT_EQ(0u, cookie_changes.size());
3138
3139 // Set partitioned cookie without nonce. Should not see the change.
3140 this->CreateAndSetCookie(
3141 cs, GURL("https://www.example.com"),
3142 "__Host-a=2; Secure; Path=/; Partitioned",
3143 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
3144 std::nullopt /* system_time */,
3145 CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")));
3146 this->DeliverChangeNotifications();
3147 ASSERT_EQ(0u, cookie_changes.size());
3148
3149 // Set partitioned cookie with nonce.
3150 this->CreateAndSetCookie(
3151 cs, GURL("https://www.example.com"),
3152 "__Host-a=3; Secure; Path=/; Partitioned",
3153 CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */,
3154 std::nullopt /* system_time */,
3155 CookiePartitionKey::FromURLForTesting(
3156 GURL("https://www.foo.com"),
3157 CookiePartitionKey::AncestorChainBit::kCrossSite, nonce));
3158 this->DeliverChangeNotifications();
3159 ASSERT_EQ(1u, cookie_changes.size());
3160 }
3161
3162 REGISTER_TYPED_TEST_SUITE_P(CookieStoreChangeGlobalTest,
3163 NoCookie,
3164 InitialCookie,
3165 InsertOne,
3166 InsertMany,
3167 DeleteOne,
3168 DeleteTwo,
3169 Overwrite,
3170 OverwriteWithHttpOnly,
3171 Deregister,
3172 DeregisterMultiple,
3173 DispatchRace,
3174 DeregisterRace,
3175 DeregisterRaceMultiple,
3176 MultipleSubscriptions,
3177 ChangeIncludesCookieAccessSemantics,
3178 PartitionedCookies);
3179
3180 REGISTER_TYPED_TEST_SUITE_P(CookieStoreChangeUrlTest,
3181 NoCookie,
3182 InitialCookie,
3183 InsertOne,
3184 InsertMany,
3185 InsertFiltering,
3186 DeleteOne,
3187 DeleteTwo,
3188 DeleteFiltering,
3189 Overwrite,
3190 OverwriteFiltering,
3191 OverwriteWithHttpOnly,
3192 Deregister,
3193 DeregisterMultiple,
3194 DispatchRace,
3195 DeregisterRace,
3196 DeregisterRaceMultiple,
3197 DifferentSubscriptionsDisjoint,
3198 DifferentSubscriptionsDomains,
3199 DifferentSubscriptionsPaths,
3200 DifferentSubscriptionsFiltering,
3201 MultipleSubscriptions,
3202 ChangeIncludesCookieAccessSemantics,
3203 PartitionedCookies,
3204 PartitionedCookies_WithNonce);
3205
3206 REGISTER_TYPED_TEST_SUITE_P(CookieStoreChangeNamedTest,
3207 NoCookie,
3208 InitialCookie,
3209 InsertOne,
3210 InsertTwo,
3211 InsertFiltering,
3212 DeleteOne,
3213 DeleteTwo,
3214 DeleteFiltering,
3215 Overwrite,
3216 OverwriteFiltering,
3217 OverwriteWithHttpOnly,
3218 Deregister,
3219 DeregisterMultiple,
3220 DispatchRace,
3221 DeregisterRace,
3222 DeregisterRaceMultiple,
3223 DifferentSubscriptionsDisjoint,
3224 DifferentSubscriptionsDomains,
3225 DifferentSubscriptionsNames,
3226 DifferentSubscriptionsPaths,
3227 DifferentSubscriptionsFiltering,
3228 MultipleSubscriptions,
3229 SubscriptionOutlivesStore,
3230 ChangeIncludesCookieAccessSemantics,
3231 PartitionedCookies,
3232 PartitionedCookies_WithNonce);
3233
3234 } // namespace net
3235
3236 #endif // NET_COOKIES_COOKIE_STORE_CHANGE_UNITTEST_H_
3237