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 <optional>
12 #include <set>
13 #include <string>
14 #include <utility>
15 #include <vector>
16
17 #include "base/functional/bind.h"
18 #include "base/strings/string_tokenizer.h"
19 #include "base/task/current_thread.h"
20 #include "base/task/single_thread_task_runner.h"
21 #include "base/test/task_environment.h"
22 #include "base/threading/thread.h"
23 #include "base/time/time.h"
24 #include "build/build_config.h"
25 #include "net/cookies/canonical_cookie.h"
26 #include "net/cookies/cookie_store.h"
27 #include "net/cookies/cookie_store_test_callbacks.h"
28 #include "net/cookies/cookie_store_test_helpers.h"
29 #include "net/cookies/test_cookie_access_delegate.h"
30 #include "testing/gtest/include/gtest/gtest.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 std::optional<base::Time> server_time = std::nullopt,
222 std::optional<base::Time> system_time = std::nullopt,
223 std::optional<CookiePartitionKey> cookie_partition_key = std::nullopt,
224 CookieSourceType source_type = CookieSourceType::kUnknown) {
225 // Ensure a different Creation date to guarantee sort order for testing
226 static base::Time last = base::Time::Min();
227 last = base::Time::Now() == last ? last + base::Microseconds(1)
228 : base::Time::Now();
229
230 auto cookie = CanonicalCookie::Create(
231 url, cookie_line, system_time.value_or(last), server_time,
232 cookie_partition_key,
233 /*block_truncated=*/true, source_type, /*status=*/nullptr);
234
235 if (!cookie)
236 return false;
237 DCHECK(cs);
238 ResultSavingCookieCallback<CookieAccessResult> callback;
239 cs->SetCanonicalCookieAsync(std::move(cookie), url, options,
240 callback.MakeCallback());
241 callback.WaitUntilDone();
242 return callback.result().status.IsInclude();
243 }
244
SetCanonicalCookie(CookieStore * cs,std::unique_ptr<CanonicalCookie> cookie,const GURL & source_url,bool can_modify_httponly)245 bool SetCanonicalCookie(CookieStore* cs,
246 std::unique_ptr<CanonicalCookie> cookie,
247 const GURL& source_url,
248 bool can_modify_httponly) {
249 DCHECK(cs);
250 ResultSavingCookieCallback<CookieAccessResult> callback;
251 CookieOptions options;
252 if (can_modify_httponly)
253 options.set_include_httponly();
254 options.set_same_site_cookie_context(
255 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
256 cs->SetCanonicalCookieAsync(std::move(cookie), source_url, options,
257 callback.MakeCallback());
258 callback.WaitUntilDone();
259 return callback.result().status.IsInclude();
260 }
261
SetCookieWithSystemTime(CookieStore * cs,const GURL & url,const std::string & cookie_line,const base::Time & system_time)262 bool SetCookieWithSystemTime(CookieStore* cs,
263 const GURL& url,
264 const std::string& cookie_line,
265 const base::Time& system_time) {
266 CookieOptions options;
267 if (!CookieStoreTestTraits::supports_http_only)
268 options.set_include_httponly();
269 options.set_same_site_cookie_context(
270 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
271 return CreateAndSetCookie(cs, url, cookie_line, options, std::nullopt,
272 std::make_optional(system_time));
273 }
274
SetCookieWithServerTime(CookieStore * cs,const GURL & url,const std::string & cookie_line,const base::Time & server_time)275 bool SetCookieWithServerTime(CookieStore* cs,
276 const GURL& url,
277 const std::string& cookie_line,
278 const base::Time& server_time) {
279 CookieOptions options;
280 if (!CookieStoreTestTraits::supports_http_only)
281 options.set_include_httponly();
282 options.set_same_site_cookie_context(
283 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
284 return CreateAndSetCookie(cs, url, cookie_line, options,
285 std::make_optional(server_time));
286 }
287
288 bool SetCookie(
289 CookieStore* cs,
290 const GURL& url,
291 const std::string& cookie_line,
292 std::optional<CookiePartitionKey> cookie_partition_key = std::nullopt,
293 CookieSourceType source_type = CookieSourceType::kUnknown) {
294 CookieOptions options;
295 if (!CookieStoreTestTraits::supports_http_only)
296 options.set_include_httponly();
297 options.set_same_site_cookie_context(
298 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
299 return CreateAndSetCookie(cs, url, cookie_line, options, std::nullopt,
300 std::nullopt, cookie_partition_key, source_type);
301 }
302
CreateAndSetCookieReturnStatus(CookieStore * cs,const GURL & url,const std::string & cookie_line)303 CookieInclusionStatus CreateAndSetCookieReturnStatus(
304 CookieStore* cs,
305 const GURL& url,
306 const std::string& cookie_line) {
307 CookieInclusionStatus create_status;
308 auto cookie = CanonicalCookie::Create(
309 url, cookie_line, base::Time::Now(), /*server_time=*/std::nullopt,
310 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
311 CookieSourceType::kUnknown, &create_status);
312 if (!cookie)
313 return create_status;
314
315 CookieOptions options;
316 if (!CookieStoreTestTraits::supports_http_only)
317 options.set_include_httponly();
318 // Allow setting SameSite cookies.
319 options.set_same_site_cookie_context(
320 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
321
322 DCHECK(cs);
323 ResultSavingCookieCallback<CookieAccessResult> callback;
324 cs->SetCanonicalCookieAsync(std::move(cookie), url, options,
325 callback.MakeCallback());
326 callback.WaitUntilDone();
327 return callback.result().status;
328 }
329
SetCanonicalCookieReturnAccessResult(CookieStore * cs,std::unique_ptr<CanonicalCookie> cookie,const GURL & source_url,bool can_modify_httponly)330 CookieAccessResult SetCanonicalCookieReturnAccessResult(
331 CookieStore* cs,
332 std::unique_ptr<CanonicalCookie> cookie,
333 const GURL& source_url,
334 bool can_modify_httponly) {
335 DCHECK(cs);
336 ResultSavingCookieCallback<CookieAccessResult> callback;
337 CookieOptions options;
338 if (can_modify_httponly)
339 options.set_include_httponly();
340 options.set_same_site_cookie_context(
341 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
342 cs->SetCanonicalCookieAsync(std::move(cookie), source_url, options,
343 callback.MakeCallback());
344 callback.WaitUntilDone();
345 return callback.result();
346 }
347
DeleteCanonicalCookie(CookieStore * cs,const CanonicalCookie & cookie)348 uint32_t DeleteCanonicalCookie(CookieStore* cs,
349 const CanonicalCookie& cookie) {
350 DCHECK(cs);
351 ResultSavingCookieCallback<uint32_t> callback;
352 cs->DeleteCanonicalCookieAsync(cookie, callback.MakeCallback());
353 callback.WaitUntilDone();
354 return callback.result();
355 }
356
DeleteCreatedInTimeRange(CookieStore * cs,const TimeRange & creation_range)357 uint32_t DeleteCreatedInTimeRange(CookieStore* cs,
358 const TimeRange& creation_range) {
359 DCHECK(cs);
360 ResultSavingCookieCallback<uint32_t> callback;
361 cs->DeleteAllCreatedInTimeRangeAsync(creation_range,
362 callback.MakeCallback());
363 callback.WaitUntilDone();
364 return callback.result();
365 }
366
DeleteAllCreatedInTimeRange(CookieStore * cs,CookieDeletionInfo delete_info)367 uint32_t DeleteAllCreatedInTimeRange(CookieStore* cs,
368 CookieDeletionInfo delete_info) {
369 DCHECK(cs);
370 ResultSavingCookieCallback<uint32_t> callback;
371 cs->DeleteAllMatchingInfoAsync(std::move(delete_info),
372 callback.MakeCallback());
373 callback.WaitUntilDone();
374 return callback.result();
375 }
376
DeleteSessionCookies(CookieStore * cs)377 uint32_t DeleteSessionCookies(CookieStore* cs) {
378 DCHECK(cs);
379 ResultSavingCookieCallback<uint32_t> callback;
380 cs->DeleteSessionCookiesAsync(callback.MakeCallback());
381 callback.WaitUntilDone();
382 return callback.result();
383 }
384
DeleteAll(CookieStore * cs)385 uint32_t DeleteAll(CookieStore* cs) {
386 DCHECK(cs);
387 ResultSavingCookieCallback<uint32_t> callback;
388 cs->DeleteAllAsync(callback.MakeCallback());
389 callback.WaitUntilDone();
390 return callback.result();
391 }
392
FindAndDeleteCookie(CookieStore * cs,const std::string & domain,const std::string & name)393 bool FindAndDeleteCookie(CookieStore* cs,
394 const std::string& domain,
395 const std::string& name) {
396 for (auto& cookie : this->GetAllCookies(cs)) {
397 if (cookie.Domain() == domain && cookie.Name() == name)
398 return this->DeleteCanonicalCookie(cs, cookie);
399 }
400
401 return false;
402 }
403
404 // Returns the CookieStore for the test - each test only uses one CookieStore.
GetCookieStore()405 CookieStore* GetCookieStore() {
406 if (!cookie_store_)
407 cookie_store_ = CookieStoreTestTraits::Create();
408 return cookie_store_.get();
409 }
410
411 // Resets CookieStore.
ResetCookieStore()412 void ResetCookieStore() { cookie_store_.reset(); }
413
414 // Compares two cookie lines.
MatchCookieLines(const std::string & line1,const std::string & line2)415 void MatchCookieLines(const std::string& line1, const std::string& line2) {
416 EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2));
417 }
418
419 // Check the cookie line by polling until equality or a timeout is reached.
MatchCookieLineWithTimeout(CookieStore * cs,const GURL & url,const std::string & line)420 void MatchCookieLineWithTimeout(CookieStore* cs,
421 const GURL& url,
422 const std::string& line) {
423 std::string cookies = GetCookies(cs, url);
424 bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
425 base::Time polling_end_date =
426 base::Time::Now() +
427 base::Milliseconds(
428 CookieStoreTestTraits::creation_time_granularity_in_ms);
429
430 while (!matched && base::Time::Now() <= polling_end_date) {
431 base::PlatformThread::Sleep(base::Milliseconds(10));
432 cookies = GetCookies(cs, url);
433 matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
434 }
435
436 EXPECT_TRUE(matched) << "\"" << cookies << "\" does not match \"" << line
437 << "\"";
438 }
439
440 const CookieURLHelper http_www_foo_;
441 const CookieURLHelper http_bar_foo_;
442 const CookieURLHelper http_www_bar_;
443 const CookieURLHelper https_www_foo_;
444 const CookieURLHelper ftp_foo_;
445 const CookieURLHelper ws_www_foo_;
446 const CookieURLHelper wss_www_foo_;
447 const CookieURLHelper www_foo_foo_;
448 const CookieURLHelper www_foo_bar_;
449 const CookieURLHelper http_baz_com_;
450 const CookieURLHelper http_bar_com_;
451 const CookieURLHelper https_www_bar_;
452
453 std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
454
455 private:
456 // Returns a set of strings of type "name=value". Fails in case of duplicate.
TokenizeCookieLine(const std::string & line)457 std::set<std::string> TokenizeCookieLine(const std::string& line) {
458 std::set<std::string> tokens;
459 base::StringTokenizer tokenizer(line, " ;");
460 while (tokenizer.GetNext())
461 EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
462 return tokens;
463 }
464
465 std::unique_ptr<CookieStore> cookie_store_;
466 };
467 TYPED_TEST_SUITE_P(CookieStoreTest);
468
TYPED_TEST_P(CookieStoreTest,FilterTest)469 TYPED_TEST_P(CookieStoreTest, FilterTest) {
470 CookieStore* cs = this->GetCookieStore();
471
472 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
473 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
474 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
475
476 std::unique_ptr<CanonicalCookie> cc(CanonicalCookie::CreateSanitizedCookie(
477 this->www_foo_foo_.url(), "A", "B", std::string(), "/foo", one_hour_ago,
478 one_hour_from_now, base::Time(), false, false,
479 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, std::nullopt,
480 /*status=*/nullptr));
481 ASSERT_TRUE(cc);
482 EXPECT_TRUE(this->SetCanonicalCookie(
483 cs, std::move(cc), this->www_foo_foo_.url(), true /*modify_httponly*/));
484
485 // Note that for the creation time to be set exactly, without modification,
486 // it must be different from the one set by the line above.
487 cc = CanonicalCookie::CreateSanitizedCookie(
488 this->www_foo_bar_.url(), "C", "D", this->www_foo_bar_.domain(), "/bar",
489 two_hours_ago, base::Time(), one_hour_ago, false, true,
490 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, std::nullopt,
491 /*status=*/nullptr);
492 ASSERT_TRUE(cc);
493 EXPECT_TRUE(this->SetCanonicalCookie(
494 cs, std::move(cc), this->www_foo_bar_.url(), true /*modify_httponly*/));
495
496 // We permit creating a a secure cookie with an HTTP URL (since the
497 // CookieAccessDelegate may permit some sites to be used as such for
498 // development environment purposes), but it can't actually be set in this
499 // test since no such delegate is configured here.
500 cc = CanonicalCookie::CreateSanitizedCookie(
501 this->http_www_foo_.url(), "E", "F", std::string(), std::string(),
502 base::Time(), base::Time(), base::Time(), true, false,
503 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt,
504 /*status=*/nullptr);
505 ASSERT_TRUE(cc);
506 EXPECT_FALSE(this->SetCanonicalCookie(
507 cs, std::move(cc), this->http_www_foo_.url(), true /*modify_httponly*/));
508
509 cc = CanonicalCookie::CreateSanitizedCookie(
510 this->https_www_foo_.url(), "E", "F", std::string(), std::string(),
511 base::Time(), base::Time(), base::Time(), true, false,
512 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt,
513 /*status=*/nullptr);
514 ASSERT_TRUE(cc);
515 EXPECT_TRUE(this->SetCanonicalCookie(
516 cs, std::move(cc), this->https_www_foo_.url(), true /*modify_httponly*/));
517
518 // Get all the cookies for a given URL, regardless of properties. This 'get()'
519 // operation shouldn't update the access time, as the test checks that the
520 // access time is set properly upon creation. Updating the access time would
521 // make that difficult.
522 CookieList cookies = this->GetAllCookiesForURL(cs, this->www_foo_foo_.url());
523 CookieList::iterator it = cookies.begin();
524
525 ASSERT_TRUE(it != cookies.end());
526 EXPECT_EQ("A", it->Name());
527 EXPECT_EQ("B", it->Value());
528 EXPECT_EQ(this->www_foo_foo_.host(), it->Domain());
529 EXPECT_EQ("/foo", it->Path());
530 EXPECT_EQ(one_hour_ago, it->CreationDate());
531 EXPECT_TRUE(it->IsPersistent());
532 // Expect expiration date is in the right range. Some cookie implementations
533 // may not record it with millisecond accuracy.
534 EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5);
535 // Some CookieStores don't store last access date.
536 if (!it->LastAccessDate().is_null())
537 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
538 EXPECT_FALSE(it->SecureAttribute());
539 EXPECT_FALSE(it->IsHttpOnly());
540
541 ASSERT_TRUE(++it == cookies.end());
542
543 // Verify that the cookie was set as 'httponly' by passing in a CookieOptions
544 // that excludes them and getting an empty result.
545 if (TypeParam::supports_http_only) {
546 net::CookieOptions options;
547 options.set_same_site_cookie_context(
548 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
549 cookies =
550 this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(), options);
551 it = cookies.begin();
552 ASSERT_TRUE(it == cookies.end());
553 }
554
555 // Get the cookie using the wide open |options|:
556 cookies = this->GetAllCookiesForURL(cs, this->www_foo_bar_.url());
557 it = cookies.begin();
558
559 ASSERT_TRUE(it != cookies.end());
560 EXPECT_EQ("C", it->Name());
561 EXPECT_EQ("D", it->Value());
562 EXPECT_EQ(this->www_foo_bar_.Format(".%D"), it->Domain());
563 EXPECT_EQ("/bar", it->Path());
564 EXPECT_EQ(two_hours_ago, it->CreationDate());
565 EXPECT_FALSE(it->IsPersistent());
566 // Some CookieStores don't store last access date.
567 if (!it->LastAccessDate().is_null())
568 EXPECT_EQ(one_hour_ago, it->LastAccessDate());
569 EXPECT_FALSE(it->SecureAttribute());
570 EXPECT_TRUE(it->IsHttpOnly());
571
572 EXPECT_TRUE(++it == cookies.end());
573
574 cookies = this->GetAllCookiesForURL(cs, this->https_www_foo_.url());
575 it = cookies.begin();
576
577 ASSERT_TRUE(it != cookies.end());
578 EXPECT_EQ("E", it->Name());
579 EXPECT_EQ("F", it->Value());
580 EXPECT_EQ("/", it->Path());
581 EXPECT_EQ(this->https_www_foo_.host(), it->Domain());
582 // Cookie should have its creation time set, and be in a reasonable range.
583 EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
584 2);
585 EXPECT_FALSE(it->IsPersistent());
586 // Some CookieStores don't store last access date.
587 if (!it->LastAccessDate().is_null())
588 EXPECT_EQ(it->CreationDate(), it->LastAccessDate());
589 EXPECT_TRUE(it->SecureAttribute());
590 EXPECT_FALSE(it->IsHttpOnly());
591
592 EXPECT_TRUE(++it == cookies.end());
593 }
594
TYPED_TEST_P(CookieStoreTest,SetCanonicalCookieTest)595 TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) {
596 CookieStore* cs = this->GetCookieStore();
597
598 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
599 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
600 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
601
602 std::string foo_foo_host(this->www_foo_foo_.url().host());
603 std::string foo_bar_domain(this->www_foo_bar_.domain());
604 std::string http_foo_host(this->http_www_foo_.url().host());
605 std::string https_foo_host(this->https_www_foo_.url().host());
606
607 EXPECT_TRUE(this->SetCanonicalCookie(
608 cs,
609 CanonicalCookie::CreateUnsafeCookieForTesting(
610 "A", "B", foo_foo_host, "/foo", one_hour_ago, one_hour_from_now,
611 base::Time(), base::Time(), false /* secure */, false /* httponly */,
612 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT),
613 this->www_foo_foo_.url(), true));
614 EXPECT_TRUE(this->SetCanonicalCookie(
615 cs,
616 CanonicalCookie::CreateUnsafeCookieForTesting(
617 "C", "D", "." + foo_bar_domain, "/bar", two_hours_ago, base::Time(),
618 one_hour_ago, one_hour_ago, false, true, CookieSameSite::LAX_MODE,
619 COOKIE_PRIORITY_DEFAULT),
620 this->www_foo_bar_.url(), true));
621
622 // A secure source is required for setting secure cookies.
623 EXPECT_TRUE(
624 this->SetCanonicalCookieReturnAccessResult(
625 cs,
626 CanonicalCookie::CreateUnsafeCookieForTesting(
627 "E", "F", http_foo_host, "/", base::Time(), base::Time(),
628 base::Time(), base::Time(), true, false,
629 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
630 this->http_www_foo_.url(), true)
631 .status.HasExclusionReason(
632 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
633
634 // A Secure cookie can be created from an insecure URL, but is rejected upon
635 // setting.
636 CookieInclusionStatus status;
637 auto cookie = CanonicalCookie::Create(
638 this->http_www_foo_.url(), "foo=1; Secure", base::Time::Now(),
639 /*server_time=*/std::nullopt, /*cookie_partition_key=*/std::nullopt,
640 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
641 EXPECT_TRUE(cookie->SecureAttribute());
642 EXPECT_TRUE(status.IsInclude());
643 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
644 cs, std::move(cookie), this->http_www_foo_.url(), true)
645 .status.HasExclusionReason(
646 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
647
648 // A secure source is also required for overwriting secure cookies. Writing
649 // a secure cookie then overwriting it from a non-secure source should fail.
650 EXPECT_TRUE(this->SetCanonicalCookie(
651 cs,
652 CanonicalCookie::CreateUnsafeCookieForTesting(
653 "E", "F", https_foo_host, "/", base::Time(), base::Time(),
654 base::Time(), base::Time(), true /* secure */, false /* httponly */,
655 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
656 this->https_www_foo_.url(), true /* modify_http_only */));
657
658 EXPECT_TRUE(
659 this->SetCanonicalCookieReturnAccessResult(
660 cs,
661 CanonicalCookie::CreateUnsafeCookieForTesting(
662 "E", "F", http_foo_host, "/", base::Time(), base::Time(),
663 base::Time(), base::Time(), true /* secure */,
664 false /* httponly */, CookieSameSite::NO_RESTRICTION,
665 COOKIE_PRIORITY_DEFAULT),
666 this->http_www_foo_.url(), true /* modify_http_only */)
667 .status.HasExclusionReason(
668 CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
669
670 if (TypeParam::supports_http_only) {
671 // Permission to modify http only cookies is required to set an
672 // httponly cookie.
673 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
674 cs,
675 CanonicalCookie::CreateUnsafeCookieForTesting(
676 "G", "H", http_foo_host, "/unique", base::Time(),
677 base::Time(), base::Time(), base::Time(),
678 false /* secure */, true /* httponly */,
679 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT),
680 this->http_www_foo_.url(), false /* modify_http_only */)
681 .status.HasExclusionReason(
682 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
683
684 // A HttpOnly cookie can be created, but is rejected
685 // upon setting if the options do not specify include_httponly.
686 CookieInclusionStatus create_status;
687 auto c = CanonicalCookie::Create(
688 this->http_www_foo_.url(), "bar=1; HttpOnly", base::Time::Now(),
689 /*server_time=*/std::nullopt,
690 /*cookie_partition_key=*/std::nullopt,
691 /*block_truncated=*/true, CookieSourceType::kUnknown, &create_status);
692 EXPECT_TRUE(c->IsHttpOnly());
693 EXPECT_TRUE(create_status.IsInclude());
694 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
695 cs, std::move(c), this->http_www_foo_.url(),
696 false /* can_modify_httponly */)
697 .status.HasExclusionReason(
698 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
699
700 // Permission to modify httponly cookies is also required to overwrite
701 // an httponly cookie.
702 EXPECT_TRUE(this->SetCanonicalCookie(
703 cs,
704 CanonicalCookie::CreateUnsafeCookieForTesting(
705 "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
706 base::Time(), base::Time(), false /* secure */, true /* httponly */,
707 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT),
708 this->http_www_foo_.url(), true /* modify_http_only */));
709
710 EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
711 cs,
712 CanonicalCookie::CreateUnsafeCookieForTesting(
713 "G", "H", http_foo_host, "/unique", base::Time(),
714 base::Time(), base::Time(), base::Time(),
715 false /* secure */, true /* httponly */,
716 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT),
717 this->http_www_foo_.url(), false /* modify_http_only */)
718 .status.HasExclusionReason(
719 CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
720 } else {
721 // Leave store in same state as if the above tests had been run.
722 EXPECT_TRUE(this->SetCanonicalCookie(
723 cs,
724 CanonicalCookie::CreateUnsafeCookieForTesting(
725 "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
726 base::Time(), base::Time(), false /* secure */, true /* httponly */,
727 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT),
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->SecureAttribute());
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->SecureAttribute());
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->SecureAttribute());
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),
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),
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),
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),
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 std::optional<base::Time> server_time =
1324 std::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