xref: /aosp_15_r20/external/cronet/net/cookies/cookie_store_change_unittest.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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