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