1 // Copyright 2012 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_UNITTEST_H_
6 #define NET_COOKIES_COOKIE_STORE_UNITTEST_H_
7
8 #include <stdint.h>
9
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <utility>
14 #include <vector>
15
16 #include "base/functional/bind.h"
17 #include "base/strings/string_tokenizer.h"
18 #include "base/task/current_thread.h"
19 #include "base/task/single_thread_task_runner.h"
20 #include "base/test/task_environment.h"
21 #include "base/threading/thread.h"
22 #include "base/time/time.h"
23 #include "build/build_config.h"
24 #include "net/cookies/canonical_cookie.h"
25 #include "net/cookies/cookie_store.h"
26 #include "net/cookies/cookie_store_test_callbacks.h"
27 #include "net/cookies/cookie_store_test_helpers.h"
28 #include "net/cookies/test_cookie_access_delegate.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/abseil-cpp/absl/types/optional.h"
31 #include "url/gurl.h"
32
33 #if BUILDFLAG(IS_IOS)
34 #include "base/ios/ios_util.h"
35 #endif
36
37 // This file declares unittest templates that can be used to test common
38 // behavior of any CookieStore implementation.
39 // See cookie_monster_unittest.cc for an example of an implementation.
40
41 namespace net {
42
43 using base::Thread;
44 using TimeRange = CookieDeletionInfo::TimeRange;
45
46 const int kTimeout = 1000;
47
48 const char kValidCookieLine[] = "A=B; path=/";
49
50 // The CookieStoreTestTraits must have the following members:
51 // struct CookieStoreTestTraits {
52 // // Factory function. Will be called at most once per test.
53 // static std::unique_ptr<CookieStore> Create();
54 //
55 // // Drains the run loop(s) used to deliver cookie change notifications.
56 // static void DeliverChangeNotifications();
57 //
58 // // The cookie store supports cookies with the exclude_httponly() option.
59 // static const bool supports_http_only;
60 //
61 // // The cookie store is able to make the difference between the ".com"
62 // // and the "com" domains.
63 // static const bool supports_non_dotted_domains;
64 //
65 // // The cookie store does not fold domains with trailing dots (so "com." and
66 // "com" are different domains).
67 // static const bool preserves_trailing_dots;
68 //
69 // // The cookie store rejects cookies for invalid schemes such as ftp.
70 // static const bool filters_schemes;
71 //
72 // // The cookie store has a bug happening when a path is a substring of
73 // // another.
74 // static const bool has_path_prefix_bug;
75 //
76 // // The cookie store forbids setting a cookie with an empty name.
77 // static const bool forbids_setting_empty_name;
78 //
79 // // The cookie store supports global tracking of cookie changes (i.e.
80 // // calls to CookieStore::AddCallbackForAllChanges()).
81 // static const bool supports_global_cookie_tracking;
82 //
83 // // The cookie store supports tracking of cookie changes for an URL (i.e.
84 // // calls to CookieStore::AddCallbackForUrl()).
85 // static const bool supports_url_cookie_tracking;
86 //
87 // // The cookie store supports tracking of named cookie changes (i.e.
88 // // calls to CookieStore::AddCallbackForCookie()).
89 // static const bool supports_named_cookie_tracking;
90 //
91 // // The cookie store supports more than one callback per cookie change type.
92 // static const bool supports_multiple_tracking_callbacks;
93 //
94 // // The cookie store correctly distinguishes between OVERWRITE and EXPLICIT
95 // // (deletion) change causes.
96 // static const bool has_exact_change_cause;
97 //
98 // // The cookie store is guaranteed to deliver cookie changes in the order
99 // // in which calls were issued. This only applies to changes coming from
100 // // _different_ calls. If a call results in a cookie overwrite, the deletion
101 // // change must still be issued before the insertion change.
102 // static const bool has_exact_change_ordering;
103 //
104 // // Time to wait between two cookie insertions to ensure that cookies have
105 // // different creation times.
106 // static const int creation_time_granularity_in_ms;
107 //
108 // // The cookie store supports setting a CookieAccessDelegate and using it to
109 // // get the access semantics for each cookie via
110 // // CookieStore::GetAllCookiesWithAccessSemanticsAsync().
111 // // If this is not supported, all access semantics will show up as UNKNOWN.
112 // static const bool supports_cookie_access_semantics;
113 // };
114
115 template <class CookieStoreTestTraits>
116 class CookieStoreTest : public testing::Test {
117 protected:
CookieStoreTest()118 CookieStoreTest()
119 : http_www_foo_("http://www.foo.com"),
120 http_bar_foo_("http://bar.foo.com"),
121 http_www_bar_("http://www.bar.com"),
122 https_www_foo_("https://www.foo.com"),
123 ftp_foo_("ftp://ftp.foo.com/"),
124 ws_www_foo_("ws://www.foo.com"),
125 wss_www_foo_("wss://www.foo.com"),
126 www_foo_foo_("http://www.foo.com/foo"),
127 www_foo_bar_("http://www.foo.com/bar"),
128 http_baz_com_("http://baz.com"),
129 http_bar_com_("http://bar.com"),
130 https_www_bar_("https://www.bar.com") {
131 // This test may be used outside of the net test suite, and thus may not
132 // have a task environment.
133 if (!base::CurrentThread::Get()) {
134 task_environment_ =
135 std::make_unique<base::test::SingleThreadTaskEnvironment>();
136 }
137 }
138
139 // Helper methods for the asynchronous Cookie Store API that call the
140 // asynchronous method and then pump the loop until the callback is invoked,
141 // finally returning the value.
142 // TODO(chlily): Consolidate some of these.
143
144 std::string GetCookies(
145 CookieStore* cs,
146 const GURL& url,
147 const CookiePartitionKeyCollection& cookie_partition_key_collection =
148 CookiePartitionKeyCollection()) {
149 DCHECK(cs);
150 CookieOptions options;
151 if (!CookieStoreTestTraits::supports_http_only)
152 options.set_include_httponly();
153 options.set_same_site_cookie_context(
154 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
155 return GetCookiesWithOptions(cs, url, options,
156 cookie_partition_key_collection);
157 }
158
159 std::string GetCookiesWithOptions(
160 CookieStore* cs,
161 const GURL& url,
162 const CookieOptions& options,
163 const CookiePartitionKeyCollection& cookie_partition_key_collection =
164 CookiePartitionKeyCollection()) {
165 return CanonicalCookie::BuildCookieLine(GetCookieListWithOptions(
166 cs, url, options, cookie_partition_key_collection));
167 }
168
169 CookieList GetCookieListWithOptions(
170 CookieStore* cs,
171 const GURL& url,
172 const CookieOptions& options,
173 const CookiePartitionKeyCollection& cookie_partition_key_collection =
174 CookiePartitionKeyCollection()) {
175 DCHECK(cs);
176 GetCookieListCallback callback;
177 cs->GetCookieListWithOptionsAsync(
178 url, options, cookie_partition_key_collection, callback.MakeCallback());
179 callback.WaitUntilDone();
180 return callback.cookies();
181 }
182
183 // This does not update the access time on the cookies.
184 CookieList GetAllCookiesForURL(
185 CookieStore* cs,
186 const GURL& url,
187 const CookiePartitionKeyCollection& cookie_partition_key_collection =
188 CookiePartitionKeyCollection()) {
189 return GetCookieListWithOptions(cs, url, CookieOptions::MakeAllInclusive(),
190 cookie_partition_key_collection);
191 }
192
193 // This does not update the access time on the cookies.
GetExcludedCookiesForURL(CookieStore * cs,const GURL & url,const CookiePartitionKeyCollection & cookie_partition_key_collection)194 CookieAccessResultList GetExcludedCookiesForURL(
195 CookieStore* cs,
196 const GURL& url,
197 const CookiePartitionKeyCollection& cookie_partition_key_collection) {
198 DCHECK(cs);
199 GetCookieListCallback callback;
200 CookieOptions options = CookieOptions::MakeAllInclusive();
201 options.set_return_excluded_cookies();
202 cs->GetCookieListWithOptionsAsync(
203 url, options, cookie_partition_key_collection, callback.MakeCallback());
204 callback.WaitUntilDone();
205 return callback.excluded_cookies();
206 }
207
GetAllCookies(CookieStore * cs)208 CookieList GetAllCookies(CookieStore* cs) {
209 DCHECK(cs);
210 GetAllCookiesCallback callback;
211 cs->GetAllCookiesAsync(callback.MakeCallback());
212 callback.WaitUntilDone();
213 return callback.cookies();
214 }
215
216 bool CreateAndSetCookie(
217 CookieStore* cs,
218 const GURL& url,
219 const std::string& cookie_line,
220 const CookieOptions& options,
221 absl::optional<base::Time> server_time = absl::nullopt,
222 absl::optional<base::Time> system_time = absl::nullopt,
223 absl::optional<CookiePartitionKey> cookie_partition_key = absl::nullopt) {
224 // Ensure a different Creation date to guarantee sort order for testing
225 static base::Time last = base::Time::Min();
226 last = base::Time::Now() == last ? last + base::Microseconds(1)
227 : base::Time::Now();
228
229 auto cookie =
230 CanonicalCookie::Create(url, cookie_line, system_time.value_or(last),
231 server_time, cookie_partition_key);
232
233 if (!cookie)
234 return false;
235 DCHECK(cs);
236 ResultSavingCookieCallback<CookieAccessResult> callback;
237 cs->SetCanonicalCookieAsync(std::move(cookie), url, options,
238 callback.MakeCallback());
239 callback.WaitUntilDone();
240 return callback.result().status.IsInclude();
241 }
242
SetCanonicalCookie(CookieStore * cs,std::unique_ptr<CanonicalCookie> cookie,const GURL & source_url,bool can_modify_httponly)243 bool SetCanonicalCookie(CookieStore* cs,
244 std::unique_ptr<CanonicalCookie> cookie,
245 const GURL& source_url,
246 bool can_modify_httponly) {
247 DCHECK(cs);
248 ResultSavingCookieCallback<CookieAccessResult> callback;
249 CookieOptions options;
250 if (can_modify_httponly)
251 options.set_include_httponly();
252 options.set_same_site_cookie_context(
253 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
254 cs->SetCanonicalCookieAsync(std::move(cookie), source_url, options,
255 callback.MakeCallback());
256 callback.WaitUntilDone();
257 return callback.result().status.IsInclude();
258 }
259
SetCookieWithSystemTime(CookieStore * cs,const GURL & url,const std::string & cookie_line,const base::Time & system_time)260 bool SetCookieWithSystemTime(CookieStore* cs,
261 const GURL& url,
262 const std::string& cookie_line,
263 const base::Time& system_time) {
264 CookieOptions options;
265 if (!CookieStoreTestTraits::supports_http_only)
266 options.set_include_httponly();
267 options.set_same_site_cookie_context(
268 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
269 return CreateAndSetCookie(cs, url, cookie_line, options, absl::nullopt,
270 absl::make_optional(system_time));
271 }
272
SetCookieWithServerTime(CookieStore * cs,const GURL & url,const std::string & cookie_line,const base::Time & server_time)273 bool SetCookieWithServerTime(CookieStore* cs,
274 const GURL& url,
275 const std::string& cookie_line,
276 const base::Time& server_time) {
277 CookieOptions options;
278 if (!CookieStoreTestTraits::supports_http_only)
279 options.set_include_httponly();
280 options.set_same_site_cookie_context(
281 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
282 return CreateAndSetCookie(cs, url, cookie_line, options,
283 absl::make_optional(server_time));
284 }
285
286 bool SetCookie(
287 CookieStore* cs,
288 const GURL& url,
289 const std::string& cookie_line,
290 absl::optional<CookiePartitionKey> cookie_partition_key = absl::nullopt) {
291 CookieOptions options;
292 if (!CookieStoreTestTraits::supports_http_only)
293 options.set_include_httponly();
294 options.set_same_site_cookie_context(
295 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
296 return CreateAndSetCookie(cs, url, cookie_line, options, absl::nullopt,
297 absl::nullopt, cookie_partition_key);
298 }
299
CreateAndSetCookieReturnStatus(CookieStore * cs,const GURL & url,const std::string & cookie_line)300 CookieInclusionStatus CreateAndSetCookieReturnStatus(
301 CookieStore* cs,
302 const GURL& url,
303 const std::string& cookie_line) {
304 CookieInclusionStatus create_status;
305 auto cookie = CanonicalCookie::Create(
306 url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
307 absl::nullopt /* cookie_partition_key */, &create_status);
308 if (!cookie)
309 return create_status;
310
311 CookieOptions options;
312 if (!CookieStoreTestTraits::supports_http_only)
313 options.set_include_httponly();
314 // Allow setting SameSite cookies.
315 options.set_same_site_cookie_context(
316 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
317
318 DCHECK(cs);
319 ResultSavingCookieCallback<CookieAccessResult> callback;
320 cs->SetCanonicalCookieAsync(std::move(cookie), url, options,
321 callback.MakeCallback());
322 callback.WaitUntilDone();
323 return callback.result().status;
324 }
325
SetCanonicalCookieReturnAccessResult(CookieStore * cs,std::unique_ptr<CanonicalCookie> cookie,const GURL & source_url,bool can_modify_httponly)326 CookieAccessResult SetCanonicalCookieReturnAccessResult(
327 CookieStore* cs,
328 std::unique_ptr<CanonicalCookie> cookie,
329 const GURL& source_url,
330 bool can_modify_httponly) {
331 DCHECK(cs);
332 ResultSavingCookieCallback<CookieAccessResult> callback;
333 CookieOptions options;
334 if (can_modify_httponly)
335 options.set_include_httponly();
336 options.set_same_site_cookie_context(
337 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
338 cs->SetCanonicalCookieAsync(std::move(cookie), source_url, options,
339 callback.MakeCallback());
340 callback.WaitUntilDone();
341 return callback.result();
342 }
343
DeleteCanonicalCookie(CookieStore * cs,const CanonicalCookie & cookie)344 uint32_t DeleteCanonicalCookie(CookieStore* cs,
345 const CanonicalCookie& cookie) {
346 DCHECK(cs);
347 ResultSavingCookieCallback<uint32_t> callback;
348 cs->DeleteCanonicalCookieAsync(cookie, callback.MakeCallback());
349 callback.WaitUntilDone();
350 return callback.result();
351 }
352
DeleteCreatedInTimeRange(CookieStore * cs,const TimeRange & creation_range)353 uint32_t DeleteCreatedInTimeRange(CookieStore* cs,
354 const TimeRange& creation_range) {
355 DCHECK(cs);
356 ResultSavingCookieCallback<uint32_t> callback;
357 cs->DeleteAllCreatedInTimeRangeAsync(creation_range,
358 callback.MakeCallback());
359 callback.WaitUntilDone();
360 return callback.result();
361 }
362
DeleteAllCreatedInTimeRange(CookieStore * cs,CookieDeletionInfo delete_info)363 uint32_t DeleteAllCreatedInTimeRange(CookieStore* cs,
364 CookieDeletionInfo delete_info) {
365 DCHECK(cs);
366 ResultSavingCookieCallback<uint32_t> callback;
367 cs->DeleteAllMatchingInfoAsync(std::move(delete_info),
368 callback.MakeCallback());
369 callback.WaitUntilDone();
370 return callback.result();
371 }
372
DeleteSessionCookies(CookieStore * cs)373 uint32_t DeleteSessionCookies(CookieStore* cs) {
374 DCHECK(cs);
375 ResultSavingCookieCallback<uint32_t> callback;
376 cs->DeleteSessionCookiesAsync(callback.MakeCallback());
377 callback.WaitUntilDone();
378 return callback.result();
379 }
380
DeleteAll(CookieStore * cs)381 uint32_t DeleteAll(CookieStore* cs) {
382 DCHECK(cs);
383 ResultSavingCookieCallback<uint32_t> callback;
384 cs->DeleteAllAsync(callback.MakeCallback());
385 callback.WaitUntilDone();
386 return callback.result();
387 }
388
FindAndDeleteCookie(CookieStore * cs,const std::string & domain,const std::string & name)389 bool FindAndDeleteCookie(CookieStore* cs,
390 const std::string& domain,
391 const std::string& name) {
392 for (auto& cookie : this->GetAllCookies(cs)) {
393 if (cookie.Domain() == domain && cookie.Name() == name)
394 return this->DeleteCanonicalCookie(cs, cookie);
395 }
396
397 return false;
398 }
399
400 // Returns the CookieStore for the test - each test only uses one CookieStore.
GetCookieStore()401 CookieStore* GetCookieStore() {
402 if (!cookie_store_)
403 cookie_store_ = CookieStoreTestTraits::Create();
404 return cookie_store_.get();
405 }
406
407 // Resets CookieStore.
ResetCookieStore()408 void ResetCookieStore() { cookie_store_.reset(); }
409
410 // Compares two cookie lines.
MatchCookieLines(const std::string & line1,const std::string & line2)411 void MatchCookieLines(const std::string& line1, const std::string& line2) {
412 EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2));
413 }
414
415 // Check the cookie line by polling until equality or a timeout is reached.
MatchCookieLineWithTimeout(CookieStore * cs,const GURL & url,const std::string & line)416 void MatchCookieLineWithTimeout(CookieStore* cs,
417 const GURL& url,
418 const std::string& line) {
419 std::string cookies = GetCookies(cs, url);
420 bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
421 base::Time polling_end_date =
422 base::Time::Now() +
423 base::Milliseconds(
424 CookieStoreTestTraits::creation_time_granularity_in_ms);
425
426 while (!matched && base::Time::Now() <= polling_end_date) {
427 base::PlatformThread::Sleep(base::Milliseconds(10));
428 cookies = GetCookies(cs, url);
429 matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
430 }
431
432 EXPECT_TRUE(matched) << "\"" << cookies << "\" does not match \"" << line
433 << "\"";
434 }
435
436 const CookieURLHelper http_www_foo_;
437 const CookieURLHelper http_bar_foo_;
438 const CookieURLHelper http_www_bar_;
439 const CookieURLHelper https_www_foo_;
440 const CookieURLHelper ftp_foo_;
441 const CookieURLHelper ws_www_foo_;
442 const CookieURLHelper wss_www_foo_;
443 const CookieURLHelper www_foo_foo_;
444 const CookieURLHelper www_foo_bar_;
445 const CookieURLHelper http_baz_com_;
446 const CookieURLHelper http_bar_com_;
447 const CookieURLHelper https_www_bar_;
448
449 std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
450
451 private:
452 // Returns a set of strings of type "name=value". Fails in case of duplicate.
TokenizeCookieLine(const std::string & line)453 std::set<std::string> TokenizeCookieLine(const std::string& line) {
454 std::set<std::string> tokens;
455 base::StringTokenizer tokenizer(line, " ;");
456 while (tokenizer.GetNext())
457 EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
458 return tokens;
459 }
460
461 std::unique_ptr<CookieStore> cookie_store_;
462 };
463 TYPED_TEST_SUITE_P(CookieStoreTest);
464
TYPED_TEST_P(CookieStoreTest,FilterTest)465 TYPED_TEST_P(CookieStoreTest, FilterTest) {
466 CookieStore* cs = this->GetCookieStore();
467
468 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
469 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
470 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
471
472 std::unique_ptr<CanonicalCookie> cc(CanonicalCookie::CreateSanitizedCookie(
473 this->www_foo_foo_.url(), "A", "B", std::string(), "/foo", one_hour_ago,
474 one_hour_from_now, base::Time(), false, false,
475 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false,
476 absl::nullopt));
477 ASSERT_TRUE(cc);
478 EXPECT_TRUE(this->SetCanonicalCookie(
479 cs, std::move(cc), this->www_foo_foo_.url(), true /*modify_httponly*/));
480
481 // Note that for the creation time to be set exactly, without modification,
482 // it must be different from the one set by the line above.
483 cc = CanonicalCookie::CreateSanitizedCookie(
484 this->www_foo_bar_.url(), "C", "D", this->www_foo_bar_.domain(), "/bar",
485 two_hours_ago, base::Time(), one_hour_ago, false, true,
486 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false,
487 absl::nullopt);
488 ASSERT_TRUE(cc);
489 EXPECT_TRUE(this->SetCanonicalCookie(
490 cs, std::move(cc), this->www_foo_bar_.url(), true /*modify_httponly*/));
491
492 // We permit creating a a secure cookie with an HTTP URL (since the
493 // CookieAccessDelegate may permit some sites to be used as such for
494 // development environment purposes), but it can't actually be set in this
495 // test since no such delegate is configured here.
496 cc = CanonicalCookie::CreateSanitizedCookie(
497 this->http_www_foo_.url(), "E", "F", std::string(), std::string(),
498 base::Time(), base::Time(), base::Time(), true, false,
499 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false,
500 absl::nullopt);
501 ASSERT_TRUE(cc);
502 EXPECT_FALSE(this->SetCanonicalCookie(
503 cs, std::move(cc), this->http_www_foo_.url(), true /*modify_httponly*/));
504
505 cc = CanonicalCookie::CreateSanitizedCookie(
506 this->https_www_foo_.url(), "E", "F", std::string(), std::string(),
507 base::Time(), base::Time(), base::Time(), true, false,
508 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false,
509 absl::nullopt);
510 ASSERT_TRUE(cc);
511 EXPECT_TRUE(this->SetCanonicalCookie(
512 cs, std::move(cc), this->https_www_foo_.url(), true /*modify_httponly*/));
513
514 // Get all the cookies for a given URL, regardless of properties. This 'get()'
515 // operation shouldn't update the access time, as the test checks that the
516 // access time is set properly upon creation. Updating the access time would
517 // make that difficult.
518 CookieList cookies = this->GetAllCookiesForURL(cs, this->www_foo_foo_.url());
519 CookieList::iterator it = cookies.begin();
520
521 ASSERT_TRUE(it != cookies.end());
522 EXPECT_EQ("A", it->Name());
523 EXPECT_EQ("B", it->Value());
524 EXPECT_EQ(this->www_foo_foo_.host(), it->Domain());
525 EXPECT_EQ("/foo", it->Path());
526 EXPECT_EQ(one_hour_ago, it->CreationDate());
527 EXPECT_TRUE(it->IsPersistent());
528 // Expect expiration date is in the right range. Some cookie implementations
529 // may not record it with millisecond accuracy.
530 EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5);
531 // Some CookieStores don't store last access date.
532 if (!it->LastAccessDate().is_null())
533 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
534 EXPECT_FALSE(it->IsSecure());
535 EXPECT_FALSE(it->IsHttpOnly());
536
537 ASSERT_TRUE(++it == cookies.end());
538
539 // Verify that the cookie was set as 'httponly' by passing in a CookieOptions
540 // that excludes them and getting an empty result.
541 if (TypeParam::supports_http_only) {
542 net::CookieOptions options;
543 options.set_same_site_cookie_context(
544 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
545 cookies =
546 this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(), options);
547 it = cookies.begin();
548 ASSERT_TRUE(it == cookies.end());
549 }
550
551 // Get the cookie using the wide open |options|:
552 cookies = this->GetAllCookiesForURL(cs, this->www_foo_bar_.url());
553 it = cookies.begin();
554
555 ASSERT_TRUE(it != cookies.end());
556 EXPECT_EQ("C", it->Name());
557 EXPECT_EQ("D", it->Value());
558 EXPECT_EQ(this->www_foo_bar_.Format(".%D"), it->Domain());
559 EXPECT_EQ("/bar", it->Path());
560 EXPECT_EQ(two_hours_ago, it->CreationDate());
561 EXPECT_FALSE(it->IsPersistent());
562 // Some CookieStores don't store last access date.
563 if (!it->LastAccessDate().is_null())
564 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
565 EXPECT_FALSE(it->IsSecure());
566 EXPECT_TRUE(it->IsHttpOnly());
567
568 EXPECT_TRUE(++it == cookies.end());
569
570 cookies = this->GetAllCookiesForURL(cs, this->https_www_foo_.url());
571 it = cookies.begin();
572
573 ASSERT_TRUE(it != cookies.end());
574 EXPECT_EQ("E", it->Name());
575 EXPECT_EQ("F", it->Value());
576 EXPECT_EQ("/", it->Path());
577 EXPECT_EQ(this->https_www_foo_.host(), it->Domain());
578 // Cookie should have its creation time set, and be in a reasonable range.
579 EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
580 2);
581 EXPECT_FALSE(it->IsPersistent());
582 // Some CookieStores don't store last access date.
583 if (!it->LastAccessDate().is_null())
584 EXPECT_EQ(it->CreationDate(), it->LastAccessDate());
585 EXPECT_TRUE(it->IsSecure());
586 EXPECT_FALSE(it->IsHttpOnly());
587
588 EXPECT_TRUE(++it == cookies.end());
589 }
590
TYPED_TEST_P(CookieStoreTest,SetCanonicalCookieTest)591 TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) {
592 CookieStore* cs = this->GetCookieStore();
593
594 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
595 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
596 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
597
598 std::string foo_foo_host(this->www_foo_foo_.url().host());
599 std::string foo_bar_domain(this->www_foo_bar_.domain());
600 std::string http_foo_host(this->http_www_foo_.url().host());
601 std::string https_foo_host(this->https_www_foo_.url().host());
602
603 EXPECT_TRUE(this->SetCanonicalCookie(
604 cs,
605 CanonicalCookie::CreateUnsafeCookieForTesting(
606 "A", "B", foo_foo_host, "/foo", one_hour_ago, one_hour_from_now,
607 base::Time(), base::Time(), false /* secure */, false /* httponly */,
608 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false),
609 this->www_foo_foo_.url(), true));
610 EXPECT_TRUE(this->SetCanonicalCookie(
611 cs,
612 CanonicalCookie::CreateUnsafeCookieForTesting(
613 "C", "D", "." + foo_bar_domain, "/bar", two_hours_ago, base::Time(),
614 one_hour_ago, one_hour_ago, false, true, CookieSameSite::LAX_MODE,
615 COOKIE_PRIORITY_DEFAULT, false),
616 this->www_foo_bar_.url(), true));
617
618 // A secure source is required for setting secure cookies.
619 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
620 cs,
621 CanonicalCookie::CreateUnsafeCookieForTesting(
622 "E", "F", http_foo_host, "/", base::Time(),
623 base::Time(), base::Time(), base::Time(), true, false,
624 CookieSameSite::NO_RESTRICTION,
625 COOKIE_PRIORITY_DEFAULT, false),
626 this->http_www_foo_.url(), true)
627 .status.HasExclusionReason(
628 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
629
630 // A Secure cookie can be created from an insecure URL, but is rejected upon
631 // setting.
632 CookieInclusionStatus status;
633 auto cookie = CanonicalCookie::Create(
634 this->http_www_foo_.url(), "foo=1; Secure", base::Time::Now(),
635 absl::nullopt /* server_time */, absl::nullopt /* cookie_partition_key */,
636 &status);
637 EXPECT_TRUE(cookie->IsSecure());
638 EXPECT_TRUE(status.IsInclude());
639 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
640 cs, std::move(cookie), this->http_www_foo_.url(), true)
641 .status.HasExclusionReason(
642 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
643
644 // A secure source is also required for overwriting secure cookies. Writing
645 // a secure cookie then overwriting it from a non-secure source should fail.
646 EXPECT_TRUE(this->SetCanonicalCookie(
647 cs,
648 CanonicalCookie::CreateUnsafeCookieForTesting(
649 "E", "F", https_foo_host, "/", base::Time(), base::Time(),
650 base::Time(), base::Time(), true /* secure */, false /* httponly */,
651 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
652 false /* same_party */),
653 this->https_www_foo_.url(), true /* modify_http_only */));
654
655 EXPECT_TRUE(
656 this->SetCanonicalCookieReturnAccessResult(
657 cs,
658 CanonicalCookie::CreateUnsafeCookieForTesting(
659 "E", "F", http_foo_host, "/", base::Time(), base::Time(),
660 base::Time(), base::Time(), true /* secure */,
661 false /* httponly */, CookieSameSite::NO_RESTRICTION,
662 COOKIE_PRIORITY_DEFAULT, false /* same_party */),
663 this->http_www_foo_.url(), true /* modify_http_only */)
664 .status.HasExclusionReason(
665 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
666
667 if (TypeParam::supports_http_only) {
668 // Permission to modify http only cookies is required to set an
669 // httponly cookie.
670 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
671 cs,
672 CanonicalCookie::CreateUnsafeCookieForTesting(
673 "G", "H", http_foo_host, "/unique", base::Time(),
674 base::Time(), base::Time(), base::Time(),
675 false /* secure */, true /* httponly */,
676 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
677 false /* same_party */),
678 this->http_www_foo_.url(), false /* modify_http_only */)
679 .status.HasExclusionReason(
680 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
681
682 // A HttpOnly cookie can be created, but is rejected
683 // upon setting if the options do not specify include_httponly.
684 CookieInclusionStatus create_status;
685 auto c = CanonicalCookie::Create(
686 this->http_www_foo_.url(), "bar=1; HttpOnly", base::Time::Now(),
687 absl::nullopt /* server_time */,
688 absl::nullopt /* cookie_partition_key */, &create_status);
689 EXPECT_TRUE(c->IsHttpOnly());
690 EXPECT_TRUE(create_status.IsInclude());
691 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
692 cs, std::move(c), this->http_www_foo_.url(),
693 false /* can_modify_httponly */)
694 .status.HasExclusionReason(
695 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
696
697 // Permission to modify httponly cookies is also required to overwrite
698 // an httponly cookie.
699 EXPECT_TRUE(this->SetCanonicalCookie(
700 cs,
701 CanonicalCookie::CreateUnsafeCookieForTesting(
702 "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
703 base::Time(), base::Time(), false /* secure */, true /* httponly */,
704 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
705 false /* same_party */),
706 this->http_www_foo_.url(), true /* modify_http_only */));
707
708 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
709 cs,
710 CanonicalCookie::CreateUnsafeCookieForTesting(
711 "G", "H", http_foo_host, "/unique", base::Time(),
712 base::Time(), base::Time(), base::Time(),
713 false /* secure */, true /* httponly */,
714 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
715 false /* same_party */),
716 this->http_www_foo_.url(), false /* modify_http_only */)
717 .status.HasExclusionReason(
718 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
719 } else {
720 // Leave store in same state as if the above tests had been run.
721 EXPECT_TRUE(this->SetCanonicalCookie(
722 cs,
723 CanonicalCookie::CreateUnsafeCookieForTesting(
724 "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
725 base::Time(), base::Time(), false /* secure */, true /* httponly */,
726 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
727 false /* same_party */),
728 this->http_www_foo_.url(), true /* modify_http_only */));
729 }
730
731 // Get all the cookies for a given URL, regardless of properties. This 'get()'
732 // operation shouldn't update the access time, as the test checks that the
733 // access time is set properly upon creation. Updating the access time would
734 // make that difficult.
735 CookieList cookies = this->GetAllCookiesForURL(cs, this->www_foo_foo_.url());
736 CookieList::iterator it = cookies.begin();
737
738 ASSERT_EQ(1u, cookies.size());
739 EXPECT_EQ("A", it->Name());
740 EXPECT_EQ("B", it->Value());
741 EXPECT_EQ(this->www_foo_foo_.host(), it->Domain());
742 EXPECT_EQ("/foo", it->Path());
743 EXPECT_EQ(one_hour_ago, it->CreationDate());
744 EXPECT_TRUE(it->IsPersistent());
745 // Expect expiration date is in the right range. Some cookie implementations
746 // may not record it with millisecond accuracy.
747 EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5);
748 // Some CookieStores don't store last access date.
749 if (!it->LastAccessDate().is_null())
750 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
751 EXPECT_FALSE(it->IsSecure());
752 EXPECT_FALSE(it->IsHttpOnly());
753
754 // Get the cookie using the wide open |options|:
755 cookies = this->GetAllCookiesForURL(cs, this->www_foo_bar_.url());
756 ASSERT_EQ(1u, cookies.size());
757 it = cookies.begin();
758
759 EXPECT_EQ("C", it->Name());
760 EXPECT_EQ("D", it->Value());
761 EXPECT_EQ(this->www_foo_bar_.Format(".%D"), it->Domain());
762 EXPECT_EQ("/bar", it->Path());
763 EXPECT_EQ(two_hours_ago, it->CreationDate());
764 EXPECT_FALSE(it->IsPersistent());
765 // Some CookieStores don't store last access date.
766 if (!it->LastAccessDate().is_null())
767 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
768 EXPECT_FALSE(it->IsSecure());
769 EXPECT_TRUE(it->IsHttpOnly());
770
771 cookies = this->GetAllCookiesForURL(cs, this->https_www_foo_.url());
772 ASSERT_EQ(1u, cookies.size());
773 it = cookies.begin();
774
775 EXPECT_EQ("E", it->Name());
776 EXPECT_EQ("F", it->Value());
777 EXPECT_EQ("/", it->Path());
778 EXPECT_EQ(this->https_www_foo_.host(), it->Domain());
779 // Cookie should have its creation time set, and be in a reasonable range.
780 EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
781 2);
782 EXPECT_FALSE(it->IsPersistent());
783 // Some CookieStores don't store last access date.
784 if (!it->LastAccessDate().is_null())
785 EXPECT_EQ(it->CreationDate(), it->LastAccessDate());
786 EXPECT_TRUE(it->IsSecure());
787 EXPECT_FALSE(it->IsHttpOnly());
788 }
789
790 // Test enforcement around setting secure cookies.
TYPED_TEST_P(CookieStoreTest,SecureEnforcement)791 TYPED_TEST_P(CookieStoreTest, SecureEnforcement) {
792 CookieStore* cs = this->GetCookieStore();
793 GURL http_url(this->http_www_foo_.url());
794 std::string http_domain(http_url.host());
795 GURL https_url(this->https_www_foo_.url());
796 std::string https_domain(https_url.host());
797
798 // Confirm that setting the secure attribute from an insecure source fails,
799 // but the other combinations work.
800 EXPECT_FALSE(this->SetCanonicalCookie(
801 cs,
802 CanonicalCookie::CreateUnsafeCookieForTesting(
803 "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
804 base::Time(), base::Time(), true, false, CookieSameSite::STRICT_MODE,
805 COOKIE_PRIORITY_DEFAULT, false /* same_party */),
806 http_url, true /*modify_httponly*/));
807 EXPECT_TRUE(this->SetCanonicalCookie(
808 cs,
809 CanonicalCookie::CreateUnsafeCookieForTesting(
810 "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
811 base::Time(), base::Time(), true, false, CookieSameSite::STRICT_MODE,
812 COOKIE_PRIORITY_DEFAULT, false /* same_party */),
813 https_url, true /*modify_httponly*/));
814 EXPECT_TRUE(this->SetCanonicalCookie(
815 cs,
816 CanonicalCookie::CreateUnsafeCookieForTesting(
817 "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
818 base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
819 COOKIE_PRIORITY_DEFAULT, false /* same_party */),
820 https_url, true /*modify_httponly*/));
821 EXPECT_TRUE(this->SetCanonicalCookie(
822 cs,
823 CanonicalCookie::CreateUnsafeCookieForTesting(
824 "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
825 base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
826 COOKIE_PRIORITY_DEFAULT, false /* same_party */),
827 http_url, true /*modify_httponly*/));
828 }
829
830 // Check that Secure cookies can be set from a localhost URL, regardless of
831 // scheme.
TYPED_TEST_P(CookieStoreTest,SecureCookieLocalhost)832 TYPED_TEST_P(CookieStoreTest, SecureCookieLocalhost) {
833 CookieStore* cs = this->GetCookieStore();
834 EXPECT_TRUE(this->CreateAndSetCookie(cs, GURL("https://localhost/path"),
835 "A=B;Secure",
836 CookieOptions::MakeAllInclusive()));
837 EXPECT_TRUE(this->CreateAndSetCookie(cs, GURL("https://127.0.0.1/path"),
838 "A=B;Secure",
839 CookieOptions::MakeAllInclusive()));
840 EXPECT_TRUE(this->CreateAndSetCookie(cs, GURL("http://localhost/path"),
841 "A=B;Secure",
842 CookieOptions::MakeAllInclusive()));
843 EXPECT_TRUE(this->CreateAndSetCookie(cs, GURL("http://127.0.0.1/path"),
844 "A=B;Secure",
845 CookieOptions::MakeAllInclusive()));
846 EXPECT_TRUE(this->CreateAndSetCookie(cs, GURL("http://[::1]/path"),
847 "A=B;Secure",
848 CookieOptions::MakeAllInclusive()));
849 }
850
851 // The iOS networking stack uses the iOS cookie parser, which we do not
852 // control. While it is spec-compliant, that does not match the practical
853 // behavior of most UAs in some cases, which we try to replicate. See
854 // https://crbug.com/638389 for more information.
TYPED_TEST_P(CookieStoreTest,EmptyKeyTest)855 TYPED_TEST_P(CookieStoreTest, EmptyKeyTest) {
856 #if !BUILDFLAG(IS_IOS)
857 CookieStore* cs = this->GetCookieStore();
858
859 GURL url1("http://foo1.bar.com");
860 EXPECT_TRUE(this->SetCookie(cs, url1, "foo"));
861 EXPECT_EQ("foo", this->GetCookies(cs, url1));
862
863 // Cookies with neither name nor value (e.g. `Set-Cookie: =`) are ignored.
864 GURL url2("http://foo2.bar.com");
865 EXPECT_TRUE(this->SetCookie(cs, url2, "foo"));
866 EXPECT_FALSE(this->SetCookie(cs, url2, "\t"));
867 EXPECT_EQ("foo", this->GetCookies(cs, url2));
868
869 GURL url3("http://foo3.bar.com");
870 EXPECT_TRUE(this->SetCookie(cs, url3, "foo"));
871 EXPECT_FALSE(this->SetCookie(cs, url3, "="));
872 EXPECT_EQ("foo", this->GetCookies(cs, url3));
873
874 GURL url4("http://foo4.bar.com");
875 EXPECT_TRUE(this->SetCookie(cs, url4, "foo"));
876 EXPECT_FALSE(this->SetCookie(cs, url4, ""));
877 EXPECT_EQ("foo", this->GetCookies(cs, url4));
878
879 GURL url5("http://foo5.bar.com");
880 EXPECT_TRUE(this->SetCookie(cs, url5, "foo"));
881 EXPECT_FALSE(this->SetCookie(cs, url5, "; bar"));
882 EXPECT_EQ("foo", this->GetCookies(cs, url5));
883
884 GURL url6("http://foo6.bar.com");
885 EXPECT_TRUE(this->SetCookie(cs, url6, "foo"));
886 EXPECT_FALSE(this->SetCookie(cs, url6, " "));
887 EXPECT_EQ("foo", this->GetCookies(cs, url6));
888 #endif
889 }
890
TYPED_TEST_P(CookieStoreTest,DomainTest)891 TYPED_TEST_P(CookieStoreTest, DomainTest) {
892 CookieStore* cs = this->GetCookieStore();
893 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
894 this->MatchCookieLines("A=B",
895 this->GetCookies(cs, this->http_www_foo_.url()));
896 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
897 this->http_www_foo_.Format("C=D; domain=.%D")));
898 this->MatchCookieLines("A=B; C=D",
899 this->GetCookies(cs, this->http_www_foo_.url()));
900
901 // Verify that A=B was set as a host cookie rather than a domain
902 // cookie -- should not be accessible from a sub sub-domain.
903 this->MatchCookieLines(
904 "C=D", this->GetCookies(
905 cs, GURL(this->http_www_foo_.Format("http://foo.www.%D"))));
906
907 // Test and make sure we find domain cookies on the same domain.
908 EXPECT_TRUE(
909 this->SetCookie(cs, this->http_www_foo_.url(),
910 this->http_www_foo_.Format("E=F; domain=.www.%D")));
911 this->MatchCookieLines("A=B; C=D; E=F",
912 this->GetCookies(cs, this->http_www_foo_.url()));
913
914 // Test setting a domain= that doesn't start w/ a dot, should
915 // treat it as a domain cookie, as if there was a pre-pended dot.
916 EXPECT_TRUE(
917 this->SetCookie(cs, this->http_www_foo_.url(),
918 this->http_www_foo_.Format("G=H; domain=www.%D")));
919 this->MatchCookieLines("A=B; C=D; E=F; G=H",
920 this->GetCookies(cs, this->http_www_foo_.url()));
921
922 // Test domain enforcement, should fail on a sub-domain or something too deep.
923 EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
924 this->http_www_foo_.Format("I=J; domain=.%R")));
925 this->MatchCookieLines(
926 std::string(),
927 this->GetCookies(cs, GURL(this->http_www_foo_.Format("http://a.%R"))));
928 EXPECT_FALSE(
929 this->SetCookie(cs, this->http_www_foo_.url(),
930 this->http_www_foo_.Format("K=L; domain=.bla.www.%D")));
931 this->MatchCookieLines(
932 "C=D; E=F; G=H",
933 this->GetCookies(cs,
934 GURL(this->http_www_foo_.Format("http://bla.www.%D"))));
935 this->MatchCookieLines("A=B; C=D; E=F; G=H",
936 this->GetCookies(cs, this->http_www_foo_.url()));
937 }
938
939 // FireFox recognizes domains containing trailing periods as valid.
940 // IE and Safari do not. Assert the expected policy here.
TYPED_TEST_P(CookieStoreTest,DomainWithTrailingDotTest)941 TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
942 CookieStore* cs = this->GetCookieStore();
943 // These two cases fail because the url, http://www.foo.com, does not match
944 // the domain given in the cookie line (due to the trailing dots), so the
945 // cookie is not created.
946 EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
947 "a=1; domain=.www.foo.com."));
948 EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
949 "b=2; domain=.www.foo.com.."));
950 this->MatchCookieLines(std::string(),
951 this->GetCookies(cs, this->http_www_foo_.url()));
952
953 GURL url_with_dot("http://www.foo.com.");
954 GURL url_with_double_dot("http://www.foo.com..");
955
956 // This succeeds because the urls match.
957 EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "a=1; domain=.www.foo.com."));
958 // This fails because two trailing dots are not allowed, so the cookie is not
959 // created.
960 EXPECT_FALSE(
961 this->SetCookie(cs, url_with_double_dot, "b=2; domain=.www.foo.com.."));
962
963 if (TypeParam::preserves_trailing_dots) {
964 // If the CookieStore preserves trailing dots, then .www.foo.com is not
965 // considered the same as .www.foo.com.
966 this->MatchCookieLines(std::string(),
967 this->GetCookies(cs, this->http_www_foo_.url()));
968 this->MatchCookieLines("a=1", this->GetCookies(cs, url_with_dot));
969 } else {
970 // If the CookieStore does not preserve trailing dots, the domains will both
971 // be folded into one.
972 this->MatchCookieLines("a=1",
973 this->GetCookies(cs, this->http_www_foo_.url()));
974 this->MatchCookieLines("a=1", this->GetCookies(cs, url_with_dot));
975 }
976 }
977
978 // Test that cookies can bet set on higher level domains.
TYPED_TEST_P(CookieStoreTest,ValidSubdomainTest)979 TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
980 CookieStore* cs = this->GetCookieStore();
981 GURL url_abcd("http://a.b.c.d.com");
982 GURL url_bcd("http://b.c.d.com");
983 GURL url_cd("http://c.d.com");
984 GURL url_d("http://d.com");
985
986 EXPECT_TRUE(this->SetCookie(cs, url_abcd, "a=1; domain=.a.b.c.d.com"));
987 EXPECT_TRUE(this->SetCookie(cs, url_abcd, "b=2; domain=.b.c.d.com"));
988 EXPECT_TRUE(this->SetCookie(cs, url_abcd, "c=3; domain=.c.d.com"));
989 EXPECT_TRUE(this->SetCookie(cs, url_abcd, "d=4; domain=.d.com"));
990
991 this->MatchCookieLines("a=1; b=2; c=3; d=4", this->GetCookies(cs, url_abcd));
992 this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs, url_bcd));
993 this->MatchCookieLines("c=3; d=4", this->GetCookies(cs, url_cd));
994 this->MatchCookieLines("d=4", this->GetCookies(cs, url_d));
995
996 // Check that the same cookie can exist on different sub-domains.
997 EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=bcd; domain=.b.c.d.com"));
998 EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=cd; domain=.c.d.com"));
999 this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
1000 this->GetCookies(cs, url_bcd));
1001 this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs, url_cd));
1002 }
1003
1004 // Test that setting a cookie which specifies an invalid domain has
1005 // no side-effect. An invalid domain in this context is one which does
1006 // not match the originating domain.
TYPED_TEST_P(CookieStoreTest,InvalidDomainTest)1007 TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
1008 CookieStore* cs = this->GetCookieStore();
1009 GURL url_foobar("http://foo.bar.com");
1010
1011 // More specific sub-domain than allowed.
1012 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "a=1; domain=.yo.foo.bar.com"));
1013
1014 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "b=2; domain=.foo.com"));
1015 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "c=3; domain=.bar.foo.com"));
1016
1017 // Different TLD, but the rest is a substring.
1018 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "d=4; domain=.foo.bar.com.net"));
1019
1020 // A substring that isn't really a parent domain.
1021 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "e=5; domain=ar.com"));
1022
1023 // Completely invalid domains:
1024 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "f=6; domain=."));
1025 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "g=7; domain=/"));
1026 EXPECT_FALSE(
1027 this->SetCookie(cs, url_foobar, "h=8; domain=http://foo.bar.com"));
1028 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "i=9; domain=..foo.bar.com"));
1029 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "j=10; domain=..bar.com"));
1030
1031 // Make sure there isn't something quirky in the domain canonicalization
1032 // that supports full URL semantics.
1033 EXPECT_FALSE(
1034 this->SetCookie(cs, url_foobar, "k=11; domain=.foo.bar.com?blah"));
1035 EXPECT_FALSE(
1036 this->SetCookie(cs, url_foobar, "l=12; domain=.foo.bar.com/blah"));
1037 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "m=13; domain=.foo.bar.com:80"));
1038 EXPECT_FALSE(this->SetCookie(cs, url_foobar, "n=14; domain=.foo.bar.com:"));
1039 EXPECT_FALSE(
1040 this->SetCookie(cs, url_foobar, "o=15; domain=.foo.bar.com#sup"));
1041
1042 this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foobar));
1043 }
1044
1045 // Make sure the cookie code hasn't gotten its subdomain string handling
1046 // reversed, missed a suffix check, etc. It's important here that the two
1047 // hosts below have the same domain + registry.
TYPED_TEST_P(CookieStoreTest,InvalidDomainSameDomainAndRegistry)1048 TYPED_TEST_P(CookieStoreTest, InvalidDomainSameDomainAndRegistry) {
1049 CookieStore* cs = this->GetCookieStore();
1050 GURL url_foocom("http://foo.com.com");
1051 EXPECT_FALSE(this->SetCookie(cs, url_foocom, "a=1; domain=.foo.com.com.com"));
1052 this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foocom));
1053 }
1054
1055 // Setting the domain without a dot on a parent domain should add a domain
1056 // cookie.
TYPED_TEST_P(CookieStoreTest,DomainWithoutLeadingDotParentDomain)1057 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotParentDomain) {
1058 CookieStore* cs = this->GetCookieStore();
1059 GURL url_hosted("http://manage.hosted.filefront.com");
1060 GURL url_filefront("http://www.filefront.com");
1061 EXPECT_TRUE(this->SetCookie(cs, url_hosted, "sawAd=1; domain=filefront.com"));
1062 this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_hosted));
1063 this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_filefront));
1064 }
1065
1066 // Even when the specified domain matches the domain of the URL exactly, treat
1067 // it as setting a domain cookie.
TYPED_TEST_P(CookieStoreTest,DomainWithoutLeadingDotSameDomain)1068 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotSameDomain) {
1069 CookieStore* cs = this->GetCookieStore();
1070 GURL url("http://www.foo.com");
1071 EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.foo.com"));
1072 this->MatchCookieLines("a=1", this->GetCookies(cs, url));
1073 this->MatchCookieLines("a=1",
1074 this->GetCookies(cs, GURL("http://sub.www.foo.com")));
1075 this->MatchCookieLines(
1076 std::string(), this->GetCookies(cs, GURL("http://something-else.com")));
1077 }
1078
1079 // Test that the domain specified in cookie string is treated case-insensitive
TYPED_TEST_P(CookieStoreTest,CaseInsensitiveDomainTest)1080 TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
1081 CookieStore* cs = this->GetCookieStore();
1082 GURL url("http://www.foo.com");
1083 EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.FOO.COM"));
1084 EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.fOO.cOM"));
1085 this->MatchCookieLines("a=1; b=2", this->GetCookies(cs, url));
1086 }
1087
TYPED_TEST_P(CookieStoreTest,TestIpAddress)1088 TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
1089 GURL url_ip("http://1.2.3.4/weee");
1090 CookieStore* cs = this->GetCookieStore();
1091 EXPECT_TRUE(this->SetCookie(cs, url_ip, kValidCookieLine));
1092 this->MatchCookieLines("A=B", this->GetCookies(cs, url_ip));
1093 }
1094
1095 // IP addresses should not be able to set domain cookies.
TYPED_TEST_P(CookieStoreTest,TestIpAddressNoDomainCookies)1096 TYPED_TEST_P(CookieStoreTest, TestIpAddressNoDomainCookies) {
1097 GURL url_ip("http://1.2.3.4/weee");
1098 CookieStore* cs = this->GetCookieStore();
1099 EXPECT_FALSE(this->SetCookie(cs, url_ip, "c=3; domain=.3.4"));
1100 this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
1101 // It should be allowed to set a cookie if domain= matches the IP address
1102 // by ignoring case and ignoring a leading dot. This matches IE/Firefox, even
1103 // though it seems a bit wrong.
1104 EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.3"));
1105 this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
1106 EXPECT_TRUE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.4"));
1107 this->MatchCookieLines("b=2", this->GetCookies(cs, url_ip));
1108 EXPECT_TRUE(this->SetCookie(cs, url_ip, "b=2; domain=.1.2.3.4"));
1109 this->MatchCookieLines("b=2", this->GetCookies(cs, url_ip));
1110
1111 #if !BUILDFLAG(IS_IOS)
1112 // Test a couple of IPv6 addresses
1113 GURL url_ip6("http://[2606:2800:220:1:248:1893:25c8:1946]");
1114 EXPECT_FALSE(this->SetCookie(
1115 cs, url_ip6, "e=1; domain=.2606:2800:220:1:248:1893:25c8:1946"));
1116 this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip6));
1117 EXPECT_TRUE(this->SetCookie(
1118 cs, url_ip6, "d=1; domain=[2606:2800:220:1:248:1893:25c8:1946]"));
1119 this->MatchCookieLines("d=1", this->GetCookies(cs, url_ip6));
1120 #endif // !BUILDFLAG(IS_IOS)
1121 }
1122
1123 // Test a TLD setting cookies on itself.
TYPED_TEST_P(CookieStoreTest,TestTLD)1124 TYPED_TEST_P(CookieStoreTest, TestTLD) {
1125 if (!TypeParam::supports_non_dotted_domains)
1126 return;
1127 CookieStore* cs = this->GetCookieStore();
1128 GURL url("http://com/");
1129
1130 // Allow setting on "com", (but only as a host cookie).
1131 EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
1132 // Domain is normalized by stripping leading `.` and lowercasing, so this
1133 // still works.
1134 EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.com"));
1135 EXPECT_TRUE(this->SetCookie(cs, url, "c=3; domain=CoM"));
1136 // Exact matches between the domain attribute and the host are treated as
1137 // host cookies, not domain cookies.
1138 EXPECT_TRUE(this->SetCookie(cs, url, "d=4; domain=com"));
1139
1140 this->MatchCookieLines("a=1; b=2; c=3; d=4", this->GetCookies(cs, url));
1141
1142 // Make sure they don't show up for a normal .com, they should be host,
1143 // domain, cookies.
1144 this->MatchCookieLines(
1145 std::string(),
1146 this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
1147 this->MatchCookieLines(std::string(),
1148 this->GetCookies(cs, GURL("http://.com/")));
1149 }
1150
1151 // http://com. should be treated the same as http://com.
TYPED_TEST_P(CookieStoreTest,TestTLDWithTerminalDot)1152 TYPED_TEST_P(CookieStoreTest, TestTLDWithTerminalDot) {
1153 CookieStore* cs = this->GetCookieStore();
1154 GURL url("http://com./index.html");
1155 EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
1156 EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.com."));
1157 EXPECT_TRUE(this->SetCookie(cs, url, "c=3; domain=CoM."));
1158 this->MatchCookieLines("a=1 b=2 c=3", this->GetCookies(cs, url));
1159 this->MatchCookieLines(
1160 std::string(),
1161 this->GetCookies(cs, GURL("http://hopefully-no-cookies.com./")));
1162 }
1163
TYPED_TEST_P(CookieStoreTest,TestSubdomainSettingCookiesOnUnknownTLD)1164 TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnUnknownTLD) {
1165 CookieStore* cs = this->GetCookieStore();
1166 GURL url("http://a.b");
1167 EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.b"));
1168 EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=b"));
1169 this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
1170 }
1171
TYPED_TEST_P(CookieStoreTest,TestSubdomainSettingCookiesOnKnownTLD)1172 TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownTLD) {
1173 CookieStore* cs = this->GetCookieStore();
1174 GURL url("http://foo.com");
1175 EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.com"));
1176 EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=com"));
1177 this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
1178 }
1179
TYPED_TEST_P(CookieStoreTest,TestSubdomainSettingCookiesOnKnownDottedTLD)1180 TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownDottedTLD) {
1181 CookieStore* cs = this->GetCookieStore();
1182 GURL url("http://foo.co.uk");
1183 EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.co.uk"));
1184 EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.uk"));
1185 this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
1186 this->MatchCookieLines(
1187 std::string(), this->GetCookies(cs, GURL("http://something-else.co.uk")));
1188 this->MatchCookieLines(
1189 std::string(), this->GetCookies(cs, GURL("http://something-else.uk")));
1190 }
1191
1192 // Intranet URLs should only be able to set host cookies.
TYPED_TEST_P(CookieStoreTest,TestSettingCookiesOnUnknownTLD)1193 TYPED_TEST_P(CookieStoreTest, TestSettingCookiesOnUnknownTLD) {
1194 CookieStore* cs = this->GetCookieStore();
1195 GURL url("http://b");
1196 EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
1197 // Even though this syntax looks like a domain cookie, it is treated as a host
1198 // cookie because `b` is treated as a public suffix.
1199 EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.b"));
1200 this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url));
1201 // Verify that this is a host cookie and does not affect a subdomain.
1202 GURL subdomain_url("http://a.b");
1203 this->MatchCookieLines("", this->GetCookies(cs, subdomain_url));
1204 }
1205
1206 // Exact matches between the domain attribute and an intranet host are
1207 // treated as host cookies, not domain cookies.
TYPED_TEST_P(CookieStoreTest,TestSettingCookiesWithHostDomainOnUnknownTLD)1208 TYPED_TEST_P(CookieStoreTest, TestSettingCookiesWithHostDomainOnUnknownTLD) {
1209 if (!TypeParam::supports_non_dotted_domains)
1210 return;
1211 CookieStore* cs = this->GetCookieStore();
1212 GURL url("http://b");
1213 EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=b"));
1214
1215 this->MatchCookieLines("a=1", this->GetCookies(cs, url));
1216
1217 // Make sure it doesn't show up for an intranet subdomain, it should be
1218 // a host, not domain, cookie.
1219 this->MatchCookieLines(
1220 std::string(),
1221 this->GetCookies(cs, GURL("http://hopefully-no-cookies.b/")));
1222 this->MatchCookieLines(std::string(),
1223 this->GetCookies(cs, GURL("http://.b/")));
1224 }
1225
1226 // Test reading/writing cookies when the domain ends with a period,
1227 // as in "www.foo.com."
TYPED_TEST_P(CookieStoreTest,TestHostEndsWithDot)1228 TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
1229 CookieStore* cs = this->GetCookieStore();
1230 GURL url("http://www.foo.com");
1231 GURL url_with_dot("http://www.foo.com.");
1232 EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
1233 this->MatchCookieLines("a=1", this->GetCookies(cs, url));
1234 // This fails because the url does not match the domain, so the cookie cannot
1235 // be created.
1236 EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.foo.com."));
1237 this->MatchCookieLines("a=1", this->GetCookies(cs, url));
1238 // This cookie can be created because the url matches the domain, and it can
1239 // be set, but the get-cookie result differs depending on whether the
1240 // CookieStore preserves trailing dots.
1241 EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.foo.com."));
1242
1243 // Do not share cookie space with the dot version of domain.
1244 // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
1245 if (TypeParam::preserves_trailing_dots) {
1246 this->MatchCookieLines("a=1", this->GetCookies(cs, url));
1247 this->MatchCookieLines("b=2", this->GetCookies(cs, url_with_dot));
1248 } else {
1249 this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url));
1250 this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url_with_dot));
1251 }
1252
1253 // Make sure there weren't any side effects.
1254 this->MatchCookieLines(
1255 std::string(),
1256 this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
1257 this->MatchCookieLines(std::string(),
1258 this->GetCookies(cs, GURL("http://.com/")));
1259 }
1260
TYPED_TEST_P(CookieStoreTest,InvalidScheme)1261 TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
1262 if (!TypeParam::filters_schemes)
1263 return;
1264
1265 CookieStore* cs = this->GetCookieStore();
1266 EXPECT_FALSE(this->SetCookie(cs, this->ftp_foo_.url(), kValidCookieLine));
1267 }
1268
TYPED_TEST_P(CookieStoreTest,InvalidScheme_Read)1269 TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
1270 if (!TypeParam::filters_schemes)
1271 return;
1272
1273 const std::string kValidDomainCookieLine =
1274 this->http_www_foo_.Format("A=B; path=/; domain=%D");
1275
1276 CookieStore* cs = this->GetCookieStore();
1277 EXPECT_TRUE(
1278 this->SetCookie(cs, this->http_www_foo_.url(), kValidDomainCookieLine));
1279 this->MatchCookieLines(std::string(),
1280 this->GetCookies(cs, this->ftp_foo_.url()));
1281 EXPECT_EQ(0U,
1282 this->GetCookieListWithOptions(cs, this->ftp_foo_.url(),
1283 CookieOptions::MakeAllInclusive())
1284 .size());
1285 }
1286
TYPED_TEST_P(CookieStoreTest,PathTest)1287 TYPED_TEST_P(CookieStoreTest, PathTest) {
1288 CookieStore* cs = this->GetCookieStore();
1289 std::string url("http://www.foo.com");
1290 EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=B; path=/wee"));
1291 this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee")));
1292 this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/")));
1293 this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/war")));
1294 this->MatchCookieLines(
1295 "A=B", this->GetCookies(cs, GURL(url + "/wee/war/more/more")));
1296 if (!TypeParam::has_path_prefix_bug)
1297 this->MatchCookieLines(std::string(),
1298 this->GetCookies(cs, GURL(url + "/weehee")));
1299 this->MatchCookieLines(std::string(), this->GetCookies(cs, GURL(url + "/")));
1300
1301 // If we add a 0 length path, it should default to /
1302 EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=C; path="));
1303 this->MatchCookieLines("A=B; A=C", this->GetCookies(cs, GURL(url + "/wee")));
1304 this->MatchCookieLines("A=C", this->GetCookies(cs, GURL(url + "/")));
1305 }
1306
TYPED_TEST_P(CookieStoreTest,EmptyExpires)1307 TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
1308 CookieStore* cs = this->GetCookieStore();
1309 CookieOptions options;
1310 if (!TypeParam::supports_http_only)
1311 options.set_include_httponly();
1312 options.set_same_site_cookie_context(
1313 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1314 GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
1315 std::string set_cookie_line =
1316 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
1317 std::string cookie_line = "ACSTM=20130308043820420042";
1318
1319 this->CreateAndSetCookie(cs, url, set_cookie_line, options);
1320 this->MatchCookieLines(cookie_line,
1321 this->GetCookiesWithOptions(cs, url, options));
1322
1323 absl::optional<base::Time> server_time =
1324 absl::make_optional(base::Time::Now() - base::Hours(1));
1325 this->CreateAndSetCookie(cs, url, set_cookie_line, options, server_time);
1326 this->MatchCookieLines(cookie_line,
1327 this->GetCookiesWithOptions(cs, url, options));
1328
1329 server_time = base::Time::Now() + base::Hours(1);
1330 this->CreateAndSetCookie(cs, url, set_cookie_line, options, server_time);
1331 this->MatchCookieLines(cookie_line,
1332 this->GetCookiesWithOptions(cs, url, options));
1333 }
1334
TYPED_TEST_P(CookieStoreTest,HttpOnlyTest)1335 TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
1336 if (!TypeParam::supports_http_only)
1337 return;
1338
1339 CookieStore* cs = this->GetCookieStore();
1340 CookieOptions options;
1341 options.set_include_httponly();
1342 options.set_same_site_cookie_context(
1343 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1344
1345 // Create a httponly cookie.
1346 EXPECT_TRUE(this->CreateAndSetCookie(cs, this->http_www_foo_.url(),
1347 "A=B; httponly", options));
1348
1349 // Check httponly read protection.
1350 this->MatchCookieLines(std::string(),
1351 this->GetCookies(cs, this->http_www_foo_.url()));
1352 this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
1353 cs, this->http_www_foo_.url(), options));
1354
1355 // Check httponly overwrite protection.
1356 EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C"));
1357 this->MatchCookieLines(std::string(),
1358 this->GetCookies(cs, this->http_www_foo_.url()));
1359 this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
1360 cs, this->http_www_foo_.url(), options));
1361 EXPECT_TRUE(
1362 this->CreateAndSetCookie(cs, this->http_www_foo_.url(), "A=C", options));
1363 this->MatchCookieLines("A=C",
1364 this->GetCookies(cs, this->http_www_foo_.url()));
1365
1366 // Check httponly create protection.
1367 EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(), "B=A; httponly"));
1368 this->MatchCookieLines("A=C", this->GetCookiesWithOptions(
1369 cs, this->http_www_foo_.url(), options));
1370 EXPECT_TRUE(this->CreateAndSetCookie(cs, this->http_www_foo_.url(),
1371 "B=A; httponly", options));
1372 this->MatchCookieLines(
1373 "A=C; B=A",
1374 this->GetCookiesWithOptions(cs, this->http_www_foo_.url(), options));
1375 this->MatchCookieLines("A=C",
1376 this->GetCookies(cs, this->http_www_foo_.url()));
1377 }
1378
TYPED_TEST_P(CookieStoreTest,TestCookieDeletion)1379 TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
1380 CookieStore* cs = this->GetCookieStore();
1381
1382 // Create a session cookie.
1383 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
1384 this->MatchCookieLines("A=B",
1385 this->GetCookies(cs, this->http_www_foo_.url()));
1386 // Delete it via Max-Age.
1387 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1388 std::string(kValidCookieLine) + "; max-age=0"));
1389 this->MatchCookieLineWithTimeout(cs, this->http_www_foo_.url(),
1390 std::string());
1391
1392 // Create a session cookie.
1393 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
1394 this->MatchCookieLines("A=B",
1395 this->GetCookies(cs, this->http_www_foo_.url()));
1396 // Delete it via Expires.
1397 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1398 std::string(kValidCookieLine) +
1399 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
1400 this->MatchCookieLines(std::string(),
1401 this->GetCookies(cs, this->http_www_foo_.url()));
1402
1403 // Create a persistent cookie.
1404 EXPECT_TRUE(
1405 this->SetCookie(cs, this->http_www_foo_.url(),
1406 kValidCookieLine + FutureCookieExpirationString()));
1407
1408 this->MatchCookieLines("A=B",
1409 this->GetCookies(cs, this->http_www_foo_.url()));
1410 // Delete it via Max-Age.
1411 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1412 std::string(kValidCookieLine) + "; max-age=0"));
1413 this->MatchCookieLineWithTimeout(cs, this->http_www_foo_.url(),
1414 std::string());
1415
1416 // Create a persistent cookie.
1417 EXPECT_TRUE(
1418 this->SetCookie(cs, this->http_www_foo_.url(),
1419 kValidCookieLine + FutureCookieExpirationString()));
1420 this->MatchCookieLines("A=B",
1421 this->GetCookies(cs, this->http_www_foo_.url()));
1422 // Delete it via Expires.
1423 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1424 std::string(kValidCookieLine) +
1425 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
1426 this->MatchCookieLines(std::string(),
1427 this->GetCookies(cs, this->http_www_foo_.url()));
1428
1429 // Create a persistent cookie.
1430 EXPECT_TRUE(
1431 this->SetCookie(cs, this->http_www_foo_.url(),
1432 kValidCookieLine + FutureCookieExpirationString()));
1433 this->MatchCookieLines("A=B",
1434 this->GetCookies(cs, this->http_www_foo_.url()));
1435 // Check that it is not deleted with significant enough clock skew.
1436 base::Time server_time;
1437 EXPECT_TRUE(
1438 base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT", &server_time));
1439 EXPECT_TRUE(this->SetCookieWithServerTime(
1440 cs, this->http_www_foo_.url(),
1441 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
1442 server_time));
1443 this->MatchCookieLines("A=B",
1444 this->GetCookies(cs, this->http_www_foo_.url()));
1445
1446 // Create a persistent cookie.
1447 EXPECT_TRUE(
1448 this->SetCookie(cs, this->http_www_foo_.url(),
1449 kValidCookieLine + FutureCookieExpirationString()));
1450 this->MatchCookieLines("A=B",
1451 this->GetCookies(cs, this->http_www_foo_.url()));
1452 // Delete it via Expires, with a unix epoch of 0.
1453 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1454 std::string(kValidCookieLine) +
1455 "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
1456 this->MatchCookieLines(std::string(),
1457 this->GetCookies(cs, this->http_www_foo_.url()));
1458 }
1459
TYPED_TEST_P(CookieStoreTest,TestDeleteAll)1460 TYPED_TEST_P(CookieStoreTest, TestDeleteAll) {
1461 CookieStore* cs = this->GetCookieStore();
1462
1463 // Set a session cookie.
1464 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
1465 EXPECT_EQ("A=B", this->GetCookies(cs, this->http_www_foo_.url()));
1466
1467 // Set a persistent cookie.
1468 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1469 "C=D" + FutureCookieExpirationString()));
1470
1471 EXPECT_EQ(2u, this->GetAllCookies(cs).size());
1472
1473 // Delete both, and make sure it works
1474 EXPECT_EQ(2u, this->DeleteAll(cs));
1475 EXPECT_EQ(0u, this->GetAllCookies(cs).size());
1476 }
1477
TYPED_TEST_P(CookieStoreTest,TestDeleteAllCreatedInTimeRange)1478 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedInTimeRange) {
1479 CookieStore* cs = this->GetCookieStore();
1480 const base::Time last_month = base::Time::Now() - base::Days(30);
1481 const base::Time last_minute = base::Time::Now() - base::Minutes(1);
1482 const base::Time next_minute = base::Time::Now() + base::Minutes(1);
1483 const base::Time next_month = base::Time::Now() + base::Days(30);
1484
1485 // Add a cookie.
1486 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1487 // Check that the cookie is in the store.
1488 this->MatchCookieLines("A=B",
1489 this->GetCookies(cs, this->http_www_foo_.url()));
1490
1491 // Remove cookies in empty intervals.
1492 EXPECT_EQ(0u, this->DeleteCreatedInTimeRange(
1493 cs, TimeRange(last_month, last_minute)));
1494 EXPECT_EQ(0u, this->DeleteCreatedInTimeRange(
1495 cs, TimeRange(next_minute, next_month)));
1496 // Check that the cookie is still there.
1497 this->MatchCookieLines("A=B",
1498 this->GetCookies(cs, this->http_www_foo_.url()));
1499
1500 // Remove the cookie with an interval defined by two dates.
1501 EXPECT_EQ(1u, this->DeleteCreatedInTimeRange(
1502 cs, TimeRange(last_minute, next_minute)));
1503 // Check that the cookie disappeared.
1504 this->MatchCookieLines(std::string(),
1505 this->GetCookies(cs, this->http_www_foo_.url()));
1506
1507 // Add another cookie.
1508 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1509 // Check that the cookie is in the store.
1510 this->MatchCookieLines("C=D",
1511 this->GetCookies(cs, this->http_www_foo_.url()));
1512
1513 // Remove the cookie with a null ending time.
1514 EXPECT_EQ(1u, this->DeleteCreatedInTimeRange(
1515 cs, TimeRange(last_minute, base::Time())));
1516 // Check that the cookie disappeared.
1517 this->MatchCookieLines(std::string(),
1518 this->GetCookies(cs, this->http_www_foo_.url()));
1519 }
1520
TYPED_TEST_P(CookieStoreTest,TestDeleteAllWithInfo)1521 TYPED_TEST_P(CookieStoreTest, TestDeleteAllWithInfo) {
1522 CookieStore* cs = this->GetCookieStore();
1523 base::Time now = base::Time::Now();
1524 base::Time last_month = base::Time::Now() - base::Days(30);
1525 base::Time last_minute = base::Time::Now() - base::Minutes(1);
1526
1527 // These 3 cookies match the time range and host.
1528 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1529 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
1530 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "Y=Z"));
1531 EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "E=B"));
1532
1533 // Delete cookies.
1534 CookieDeletionInfo delete_info(now, base::Time::Max());
1535 delete_info.value_for_testing = "B";
1536 EXPECT_EQ(2u, // Deletes A=B, E=B
1537 this->DeleteAllCreatedInTimeRange(cs, std::move(delete_info)));
1538
1539 // Check that we deleted the right ones.
1540 this->MatchCookieLines("C=D;Y=Z",
1541 this->GetCookies(cs, this->https_www_foo_.url()));
1542
1543 // Finally, check that we don't delete cookies when our time range is off.
1544 delete_info = CookieDeletionInfo(last_month, last_minute);
1545 delete_info.value_for_testing = "D";
1546 EXPECT_EQ(0u, this->DeleteAllCreatedInTimeRange(cs, std::move(delete_info)));
1547 this->MatchCookieLines("C=D;Y=Z",
1548 this->GetCookies(cs, this->https_www_foo_.url()));
1549 // Same thing, but with a good time range.
1550 delete_info = CookieDeletionInfo(now, base::Time::Max());
1551 delete_info.value_for_testing = "D";
1552 EXPECT_EQ(1u, this->DeleteAllCreatedInTimeRange(cs, std::move(delete_info)));
1553 this->MatchCookieLines("Y=Z",
1554 this->GetCookies(cs, this->https_www_foo_.url()));
1555 }
1556
TYPED_TEST_P(CookieStoreTest,TestSecure)1557 TYPED_TEST_P(CookieStoreTest, TestSecure) {
1558 CookieStore* cs = this->GetCookieStore();
1559
1560 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
1561 this->MatchCookieLines("A=B",
1562 this->GetCookies(cs, this->http_www_foo_.url()));
1563 this->MatchCookieLines("A=B",
1564 this->GetCookies(cs, this->https_www_foo_.url()));
1565
1566 EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "A=B; secure"));
1567 // The secure should overwrite the non-secure.
1568 this->MatchCookieLines(std::string(),
1569 this->GetCookies(cs, this->http_www_foo_.url()));
1570 this->MatchCookieLines("A=B",
1571 this->GetCookies(cs, this->https_www_foo_.url()));
1572
1573 EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "D=E; secure"));
1574 this->MatchCookieLines(std::string(),
1575 this->GetCookies(cs, this->http_www_foo_.url()));
1576 this->MatchCookieLines("A=B; D=E",
1577 this->GetCookies(cs, this->https_www_foo_.url()));
1578
1579 EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "A=B"));
1580 // The non-secure should overwrite the secure.
1581 this->MatchCookieLines("A=B",
1582 this->GetCookies(cs, this->http_www_foo_.url()));
1583 this->MatchCookieLines("D=E; A=B",
1584 this->GetCookies(cs, this->https_www_foo_.url()));
1585 }
1586
1587 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
TYPED_TEST_P(CookieStoreTest,NetUtilCookieTest)1588 TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
1589 const GURL test_url("http://mojo.jojo.foo.com/");
1590
1591 CookieStore* cs = this->GetCookieStore();
1592
1593 EXPECT_TRUE(this->SetCookie(cs, test_url, "foo=bar"));
1594 std::string value = this->GetCookies(cs, test_url);
1595 this->MatchCookieLines("foo=bar", value);
1596
1597 // test that we can retrieve all cookies:
1598 EXPECT_TRUE(this->SetCookie(cs, test_url, "x=1"));
1599 EXPECT_TRUE(this->SetCookie(cs, test_url, "y=2"));
1600
1601 std::string result = this->GetCookies(cs, test_url);
1602 EXPECT_FALSE(result.empty());
1603 EXPECT_NE(result.find("x=1"), std::string::npos) << result;
1604 EXPECT_NE(result.find("y=2"), std::string::npos) << result;
1605 }
1606
TYPED_TEST_P(CookieStoreTest,OverwritePersistentCookie)1607 TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
1608 GURL url_foo("http://www.foo.com/");
1609 GURL url_chromium("http://chromium.org");
1610 CookieStore* cs = this->GetCookieStore();
1611
1612 // Insert a cookie "a" for path "/path1"
1613 EXPECT_TRUE(this->SetCookie(
1614 cs, url_foo, "a=val1; path=/path1" + FutureCookieExpirationString()));
1615
1616 // Insert a cookie "b" for path "/path1"
1617 EXPECT_TRUE(this->SetCookie(
1618 cs, url_foo, "b=val1; path=/path1" + FutureCookieExpirationString()));
1619
1620 // Insert a cookie "b" for path "/path1", that is httponly. This should
1621 // overwrite the non-http-only version.
1622 CookieOptions allow_httponly;
1623 allow_httponly.set_include_httponly();
1624 allow_httponly.set_same_site_cookie_context(
1625 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1626 EXPECT_TRUE(this->CreateAndSetCookie(
1627 cs, url_foo,
1628 "b=val2; path=/path1; httponly" + FutureCookieExpirationString(),
1629 allow_httponly));
1630
1631 // Insert a cookie "a" for path "/path1". This should overwrite.
1632 EXPECT_TRUE(this->SetCookie(
1633 cs, url_foo, "a=val33; path=/path1" + FutureCookieExpirationString()));
1634
1635 // Insert a cookie "a" for path "/path2". This should NOT overwrite
1636 // cookie "a", since the path is different.
1637 EXPECT_TRUE(this->SetCookie(
1638 cs, url_foo, "a=val9; path=/path2" + FutureCookieExpirationString()));
1639
1640 // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
1641 // Although the name and path match, the hostnames do not, so shouldn't
1642 // overwrite.
1643 EXPECT_TRUE(
1644 this->SetCookie(cs, url_chromium,
1645 "a=val99; path=/path1" + FutureCookieExpirationString()));
1646
1647 if (TypeParam::supports_http_only) {
1648 this->MatchCookieLines(
1649 "a=val33", this->GetCookies(cs, GURL("http://www.foo.com/path1")));
1650 } else {
1651 this->MatchCookieLines(
1652 "a=val33; b=val2",
1653 this->GetCookies(cs, GURL("http://www.foo.com/path1")));
1654 }
1655 this->MatchCookieLines(
1656 "a=val9", this->GetCookies(cs, GURL("http://www.foo.com/path2")));
1657 this->MatchCookieLines(
1658 "a=val99", this->GetCookies(cs, GURL("http://chromium.org/path1")));
1659 }
1660
1661 // Note that accepting an empty name is contrary to spec; see
1662 // https://tools.ietf.org/html/rfc6265#section-4.1.1. However, we do it
1663 // for web compatibility; see http://inikulin.github.io/cookie-compat/
1664 // (specifically the "foo" and "=a" tests). This test is present in Chromium
1665 // so that a flag is raised if this behavior is changed.
1666 // On IOS we use the system cookie store which has Safari's behavior, so
1667 // the test is skipped.
TYPED_TEST_P(CookieStoreTest,EmptyName)1668 TYPED_TEST_P(CookieStoreTest, EmptyName) {
1669 if (TypeParam::forbids_setting_empty_name)
1670 return;
1671
1672 GURL url_foo("http://www.foo.com/");
1673 CookieStore* cs = this->GetCookieStore();
1674
1675 CookieOptions options;
1676 if (!TypeParam::supports_http_only)
1677 options.set_include_httponly();
1678 options.set_same_site_cookie_context(
1679 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1680
1681 EXPECT_TRUE(this->CreateAndSetCookie(cs, url_foo, "a", options));
1682 CookieList list = this->GetAllCookiesForURL(cs, url_foo);
1683 EXPECT_EQ(1u, list.size());
1684 EXPECT_EQ("", list[0].Name());
1685 EXPECT_EQ("a", list[0].Value());
1686 EXPECT_EQ(1u, this->DeleteAll(cs));
1687
1688 EXPECT_TRUE(this->CreateAndSetCookie(cs, url_foo, "=b", options));
1689 list = this->GetAllCookiesForURL(cs, url_foo);
1690 EXPECT_EQ(1u, list.size());
1691 EXPECT_EQ("", list[0].Name());
1692 EXPECT_EQ("b", list[0].Value());
1693 EXPECT_EQ(1u, this->DeleteAll(cs));
1694 }
1695
TYPED_TEST_P(CookieStoreTest,CookieOrdering)1696 TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
1697 // Put a random set of cookies into a store and make sure they're returned in
1698 // the right order.
1699 // Cookies should be sorted by path length and creation time, as per RFC6265.
1700 CookieStore* cs = this->GetCookieStore();
1701 EXPECT_TRUE(
1702 this->SetCookie(cs, GURL("http://d.c.b.a.foo.com/aa/x.html"), "c=1"));
1703 EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
1704 "d=1; domain=b.a.foo.com"));
1705 base::PlatformThread::Sleep(
1706 base::Milliseconds(TypeParam::creation_time_granularity_in_ms));
1707 EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
1708 "a=4; domain=b.a.foo.com"));
1709 base::PlatformThread::Sleep(
1710 base::Milliseconds(TypeParam::creation_time_granularity_in_ms));
1711 EXPECT_TRUE(this->SetCookie(cs, GURL("http://c.b.a.foo.com/aa/bb/cc/x.html"),
1712 "e=1; domain=c.b.a.foo.com"));
1713 EXPECT_TRUE(
1714 this->SetCookie(cs, GURL("http://d.c.b.a.foo.com/aa/bb/x.html"), "b=1"));
1715 EXPECT_TRUE(this->SetCookie(cs, GURL("http://news.bbc.co.uk/midpath/x.html"),
1716 "g=10"));
1717 EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
1718 this->GetCookies(cs, GURL("http://d.c.b.a.foo.com/aa/bb/cc/dd")));
1719
1720 CookieOptions options;
1721 options.set_same_site_cookie_context(
1722 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
1723
1724 CookieList cookies = this->GetCookieListWithOptions(
1725 cs, GURL("http://d.c.b.a.foo.com/aa/bb/cc/dd"), options);
1726 CookieList::const_iterator it = cookies.begin();
1727
1728 ASSERT_TRUE(it != cookies.end());
1729 EXPECT_EQ("d", it->Name());
1730
1731 ASSERT_TRUE(++it != cookies.end());
1732 EXPECT_EQ("a", it->Name());
1733
1734 ASSERT_TRUE(++it != cookies.end());
1735 EXPECT_EQ("e", it->Name());
1736
1737 ASSERT_TRUE(++it != cookies.end());
1738 EXPECT_EQ("b", it->Name());
1739
1740 ASSERT_TRUE(++it != cookies.end());
1741 EXPECT_EQ("c", it->Name());
1742
1743 EXPECT_TRUE(++it == cookies.end());
1744 }
1745
1746 // Check that GetAllCookiesAsync returns cookies from multiple domains, in the
1747 // correct order.
TYPED_TEST_P(CookieStoreTest,GetAllCookiesAsync)1748 TYPED_TEST_P(CookieStoreTest, GetAllCookiesAsync) {
1749 CookieStore* cs = this->GetCookieStore();
1750
1751 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/a"));
1752 EXPECT_TRUE(this->SetCookie(cs, this->http_baz_com_.url(), "C=D;/"));
1753 EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "E=F; path=/bar"));
1754
1755 // Check cookies for url.
1756 CookieList cookies = this->GetAllCookies(cs);
1757 CookieList::const_iterator it = cookies.begin();
1758
1759 ASSERT_TRUE(it != cookies.end());
1760 EXPECT_EQ(this->http_bar_com_.host(), it->Domain());
1761 EXPECT_EQ("/bar", it->Path());
1762 EXPECT_EQ("E", it->Name());
1763 EXPECT_EQ("F", it->Value());
1764
1765 ASSERT_TRUE(++it != cookies.end());
1766 EXPECT_EQ(this->http_www_foo_.host(), it->Domain());
1767 EXPECT_EQ("/a", it->Path());
1768 EXPECT_EQ("A", it->Name());
1769 EXPECT_EQ("B", it->Value());
1770
1771 ASSERT_TRUE(++it != cookies.end());
1772 EXPECT_EQ(this->http_baz_com_.host(), it->Domain());
1773 EXPECT_EQ("/", it->Path());
1774 EXPECT_EQ("C", it->Name());
1775 EXPECT_EQ("D", it->Value());
1776
1777 ASSERT_TRUE(++it == cookies.end());
1778 }
1779
TYPED_TEST_P(CookieStoreTest,GetAllCookiesWithAccessSemanticsAsync)1780 TYPED_TEST_P(CookieStoreTest, GetAllCookiesWithAccessSemanticsAsync) {
1781 CookieStore* cs = this->GetCookieStore();
1782 auto access_delegate = std::make_unique<TestCookieAccessDelegate>();
1783 TestCookieAccessDelegate* test_delegate = access_delegate.get();
1784 // if !supports_cookie_access_semantics, the delegate will be stored but will
1785 // not be used.
1786 cs->SetCookieAccessDelegate(std::move(access_delegate));
1787
1788 test_delegate->SetExpectationForCookieDomain("domain1.test",
1789 CookieAccessSemantics::LEGACY);
1790 test_delegate->SetExpectationForCookieDomain(
1791 "domain2.test", CookieAccessSemantics::NONLEGACY);
1792 test_delegate->SetExpectationForCookieDomain("domain3.test",
1793 CookieAccessSemantics::UNKNOWN);
1794
1795 this->CreateAndSetCookie(cs, GURL("http://domain1.test"), "cookie=1",
1796 CookieOptions::MakeAllInclusive());
1797 this->CreateAndSetCookie(cs, GURL("http://domain2.test"), "cookie=1",
1798 CookieOptions::MakeAllInclusive());
1799 this->CreateAndSetCookie(cs, GURL("http://domain3.test"), "cookie=1",
1800 CookieOptions::MakeAllInclusive());
1801 this->CreateAndSetCookie(cs, GURL("http://domain4.test"), "cookie=1",
1802 CookieOptions::MakeAllInclusive());
1803
1804 GetAllCookiesWithAccessSemanticsCallback callback;
1805 cs->GetAllCookiesWithAccessSemanticsAsync(callback.MakeCallback());
1806 callback.WaitUntilDone();
1807 EXPECT_TRUE(callback.was_run());
1808
1809 EXPECT_EQ(callback.cookies().size(), callback.access_semantics_list().size());
1810 EXPECT_EQ(4u, callback.access_semantics_list().size());
1811 EXPECT_EQ("domain1.test", callback.cookies()[0].Domain());
1812 EXPECT_EQ("domain2.test", callback.cookies()[1].Domain());
1813 EXPECT_EQ("domain3.test", callback.cookies()[2].Domain());
1814 EXPECT_EQ("domain4.test", callback.cookies()[3].Domain());
1815
1816 if (!TypeParam::supports_cookie_access_semantics) {
1817 for (CookieAccessSemantics semantics : callback.access_semantics_list()) {
1818 EXPECT_EQ(CookieAccessSemantics::UNKNOWN, semantics);
1819 }
1820 } else {
1821 EXPECT_EQ(CookieAccessSemantics::LEGACY,
1822 callback.access_semantics_list()[0]);
1823 EXPECT_EQ(CookieAccessSemantics::NONLEGACY,
1824 callback.access_semantics_list()[1]);
1825 EXPECT_EQ(CookieAccessSemantics::UNKNOWN,
1826 callback.access_semantics_list()[2]);
1827 EXPECT_EQ(CookieAccessSemantics::UNKNOWN,
1828 callback.access_semantics_list()[3]);
1829 }
1830 }
1831
TYPED_TEST_P(CookieStoreTest,DeleteCanonicalCookieAsync)1832 TYPED_TEST_P(CookieStoreTest, DeleteCanonicalCookieAsync) {
1833 CookieStore* cs = this->GetCookieStore();
1834
1835 // Set two cookies with the same name, and make sure both are set.
1836 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B;Path=/foo"));
1837 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C;Path=/bar"));
1838 EXPECT_EQ(2u, this->GetAllCookies(cs).size());
1839 EXPECT_EQ("A=B", this->GetCookies(cs, this->www_foo_foo_.url()));
1840 EXPECT_EQ("A=C", this->GetCookies(cs, this->www_foo_bar_.url()));
1841
1842 // Delete the "/foo" cookie, and make sure only it was deleted.
1843 CookieList cookies = this->GetCookieListWithOptions(
1844 cs, this->www_foo_foo_.url(), CookieOptions::MakeAllInclusive());
1845 ASSERT_EQ(1u, cookies.size());
1846 EXPECT_EQ(1u, this->DeleteCanonicalCookie(cs, cookies[0]));
1847 EXPECT_EQ(1u, this->GetAllCookies(cs).size());
1848 EXPECT_EQ("", this->GetCookies(cs, this->www_foo_foo_.url()));
1849 EXPECT_EQ("A=C", this->GetCookies(cs, this->www_foo_bar_.url()));
1850
1851 // Deleting the "/foo" cookie again should fail.
1852 EXPECT_EQ(0u, this->DeleteCanonicalCookie(cs, cookies[0]));
1853
1854 // Try to delete the "/bar" cookie after overwriting it with a new cookie.
1855 cookies = this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(),
1856 CookieOptions::MakeAllInclusive());
1857 ASSERT_EQ(1u, cookies.size());
1858 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=D;Path=/bar"));
1859 EXPECT_EQ(0u, this->DeleteCanonicalCookie(cs, cookies[0]));
1860 EXPECT_EQ(1u, this->GetAllCookies(cs).size());
1861 EXPECT_EQ("A=D", this->GetCookies(cs, this->www_foo_bar_.url()));
1862
1863 // Delete the new "/bar" cookie.
1864 cookies = this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(),
1865 CookieOptions::MakeAllInclusive());
1866 ASSERT_EQ(1u, cookies.size());
1867 EXPECT_EQ(1u, this->DeleteCanonicalCookie(cs, cookies[0]));
1868 EXPECT_EQ(0u, this->GetAllCookies(cs).size());
1869 EXPECT_EQ("", this->GetCookies(cs, this->www_foo_bar_.url()));
1870 }
1871
TYPED_TEST_P(CookieStoreTest,DeleteSessionCookie)1872 TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
1873 CookieStore* cs = this->GetCookieStore();
1874 // Create a session cookie and a persistent cookie.
1875 EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
1876 std::string(kValidCookieLine)));
1877 EXPECT_TRUE(this->SetCookie(
1878 cs, this->http_www_foo_.url(),
1879 this->http_www_foo_.Format("C=D; path=/; domain=%D" +
1880 FutureCookieExpirationString())));
1881 this->MatchCookieLines("A=B; C=D",
1882 this->GetCookies(cs, this->http_www_foo_.url()));
1883 // Delete the session cookie.
1884 this->DeleteSessionCookies(cs);
1885 // Check that the session cookie has been deleted but not the persistent one.
1886 EXPECT_EQ("C=D", this->GetCookies(cs, this->http_www_foo_.url()));
1887 }
1888
1889 REGISTER_TYPED_TEST_SUITE_P(CookieStoreTest,
1890 FilterTest,
1891 SetCanonicalCookieTest,
1892 SecureEnforcement,
1893 SecureCookieLocalhost,
1894 EmptyKeyTest,
1895 DomainTest,
1896 DomainWithTrailingDotTest,
1897 ValidSubdomainTest,
1898 InvalidDomainTest,
1899 InvalidDomainSameDomainAndRegistry,
1900 DomainWithoutLeadingDotParentDomain,
1901 DomainWithoutLeadingDotSameDomain,
1902 CaseInsensitiveDomainTest,
1903 TestIpAddress,
1904 TestIpAddressNoDomainCookies,
1905 TestTLD,
1906 TestTLDWithTerminalDot,
1907 TestSubdomainSettingCookiesOnUnknownTLD,
1908 TestSubdomainSettingCookiesOnKnownTLD,
1909 TestSubdomainSettingCookiesOnKnownDottedTLD,
1910 TestSettingCookiesOnUnknownTLD,
1911 TestSettingCookiesWithHostDomainOnUnknownTLD,
1912 TestHostEndsWithDot,
1913 InvalidScheme,
1914 InvalidScheme_Read,
1915 PathTest,
1916 EmptyExpires,
1917 HttpOnlyTest,
1918 TestCookieDeletion,
1919 TestDeleteAll,
1920 TestDeleteAllCreatedInTimeRange,
1921 TestDeleteAllWithInfo,
1922 TestSecure,
1923 NetUtilCookieTest,
1924 OverwritePersistentCookie,
1925 EmptyName,
1926 CookieOrdering,
1927 GetAllCookiesAsync,
1928 GetAllCookiesWithAccessSemanticsAsync,
1929 DeleteCanonicalCookieAsync,
1930 DeleteSessionCookie);
1931
1932 } // namespace net
1933
1934 #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_
1935