1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ios/net/cookies/cookie_store_ios.h"
7 #import <Foundation/Foundation.h>
9 #include "base/bind_helpers.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/sys_string_conversions.h"
12 #import "net/base/mac/url_conversions.h"
13 #include "net/cookies/cookie_store_unittest.h"
14 #include "testing/gtest/include/gtest/gtest.h"
17 // Clears the underlying NSHTTPCookieStorage.
19 NSHTTPCookieStorage* store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
20 [store setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
21 NSArray* cookies = [store cookies];
22 for (NSHTTPCookie* cookie in cookies)
23 [store deleteCookie:cookie];
24 EXPECT_EQ(0u, [[store cookies] count]);
30 struct CookieStoreIOSTestTraits {
31 static net::CookieStore* Create() {
33 CookieStoreIOS* store = new CookieStoreIOS(nullptr);
34 store->synchronization_state_ = CookieStoreIOS::SYNCHRONIZED;
38 static const bool is_cookie_monster = false;
39 static const bool supports_http_only = false;
40 static const bool supports_non_dotted_domains = false;
41 static const bool supports_trailing_dots = false;
42 static const bool filters_schemes = false;
43 static const bool has_path_prefix_bug = true;
44 static const int creation_time_granularity_in_ms = 1000;
46 base::MessageLoop loop_;
49 struct InactiveCookieStoreIOSTestTraits {
50 static scoped_refptr<net::CookieStore> Create() {
51 return new CookieStoreIOS(nullptr);
54 static const bool is_cookie_monster = false;
55 static const bool supports_http_only = false;
56 static const bool supports_non_dotted_domains = true;
57 static const bool supports_trailing_dots = true;
58 static const bool filters_schemes = false;
59 static const bool has_path_prefix_bug = false;
60 static const int creation_time_granularity_in_ms = 0;
62 base::MessageLoop loop_;
65 // RoundTripTestCookieStore is un-synchronized and re-synchronized after all
66 // cookie operations. This means all system cookies are converted to Chrome
67 // cookies and converted back.
68 // The purpose of this class is to test that cookie conversions do not break the
70 class RoundTripTestCookieStore : public net::CookieStore {
72 RoundTripTestCookieStore()
73 : store_(new CookieStoreIOS(nullptr)),
74 dummy_store_(new CookieStoreIOS(nullptr)) {
75 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
78 // Inherited CookieStore methods.
79 void SetCookieWithOptionsAsync(const GURL& url,
80 const std::string& cookie_line,
81 const net::CookieOptions& options,
82 const SetCookiesCallback& callback) override {
84 store_->SetCookieWithOptionsAsync(url, cookie_line, options, callback);
87 void GetCookiesWithOptionsAsync(const GURL& url,
88 const net::CookieOptions& options,
89 const GetCookiesCallback& callback) override {
91 store_->GetCookiesWithOptionsAsync(url, options, callback);
94 void GetAllCookiesForURLAsync(
96 const GetCookieListCallback& callback) override {
98 store_->GetAllCookiesForURLAsync(url, callback);
101 void DeleteCookieAsync(const GURL& url,
102 const std::string& cookie_name,
103 const base::Closure& callback) override {
105 store_->DeleteCookieAsync(url, cookie_name, callback);
108 net::CookieMonster* GetCookieMonster() override { return nullptr; }
110 void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
111 const base::Time& delete_end,
112 const DeleteCallback& callback) override {
114 store_->DeleteAllCreatedBetweenAsync(delete_begin, delete_end, callback);
117 void DeleteAllCreatedBetweenForHostAsync(
118 const base::Time delete_begin,
119 const base::Time delete_end,
121 const DeleteCallback& callback) override {
123 store_->DeleteAllCreatedBetweenForHostAsync(delete_begin, delete_end, url,
127 void DeleteSessionCookiesAsync(const DeleteCallback& callback) override {
129 store_->DeleteSessionCookiesAsync(callback);
132 scoped_ptr<CookieStore::CookieChangedSubscription> AddCallbackForCookie(
134 const std::string& name,
135 const CookieChangedCallback& callback) override {
136 return scoped_ptr<CookieStore::CookieChangedSubscription>();
140 ~RoundTripTestCookieStore() override { store_->UnSynchronize(); }
144 CookieStoreIOS::SwitchSynchronizedStore(store_.get(), dummy_store_.get());
145 // Check that the system store is empty, because it is synchronized with
146 // |dummy_store_| which is empty.
147 NSHTTPCookieStorage* store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
148 EXPECT_EQ(0u, [[store cookies] count]);
149 CookieStoreIOS::SwitchSynchronizedStore(dummy_store_.get(), store_.get());
152 scoped_refptr<CookieStoreIOS> store_;
153 // |dummy_store_| is not directly used, but is needed to make |store_|
155 scoped_refptr<CookieStoreIOS> dummy_store_;
158 struct RoundTripTestCookieStoreTraits {
159 static scoped_refptr<net::CookieStore> Create() {
161 return new RoundTripTestCookieStore();
164 static const bool is_cookie_monster = false;
165 static const bool supports_http_only = false;
166 static const bool supports_non_dotted_domains = false;
167 static const bool supports_trailing_dots = false;
168 static const bool filters_schemes = false;
169 static const bool has_path_prefix_bug = true;
170 static const int creation_time_granularity_in_ms = 1000;
177 INSTANTIATE_TYPED_TEST_CASE_P(CookieStoreIOS,
179 CookieStoreIOSTestTraits);
181 INSTANTIATE_TYPED_TEST_CASE_P(InactiveCookieStoreIOS,
183 InactiveCookieStoreIOSTestTraits);
185 INSTANTIATE_TYPED_TEST_CASE_P(RoundTripTestCookieStore,
187 RoundTripTestCookieStoreTraits);
193 // Test net::CookieMonster::PersistentCookieStore allowing to control when the
194 // initialization completes.
195 class TestPersistentCookieStore
196 : public net::CookieMonster::PersistentCookieStore {
198 TestPersistentCookieStore()
199 : kTestCookieURL("http://foo.google.com/bar"), flushed_(false) {}
201 // Runs the completion callback with a "a=b" cookie.
202 void RunLoadedCallback() {
203 std::vector<net::CanonicalCookie*> cookies;
204 net::CookieOptions options;
205 options.set_include_httponly();
206 cookies.push_back(net::CanonicalCookie::Create(kTestCookieURL, "a=b",
207 base::Time::Now(), options));
208 // Some canonical cookies cannot be converted into System cookies, for
209 // example if value is not valid utf8. Such cookies are ignored.
210 net::CanonicalCookie* bad_canonical_cookie = new net::CanonicalCookie(
211 kTestCookieURL, "name", "\x81r\xe4\xbd\xa0\xe5\xa5\xbd", "domain",
213 base::Time(), // creation
214 base::Time(), // expires
215 base::Time(), // last_access
218 false, // first_party_only
219 net::COOKIE_PRIORITY_DEFAULT);
220 cookies.push_back(bad_canonical_cookie);
221 loaded_callback_.Run(cookies);
224 bool flushed() { return flushed_; }
227 // net::CookieMonster::PersistentCookieStore implementation:
228 void Load(const LoadedCallback& loaded_callback) override {
229 loaded_callback_ = loaded_callback;
232 void LoadCookiesForKey(const std::string& key,
233 const LoadedCallback& loaded_callback) override {
234 loaded_callback_ = loaded_callback;
237 void AddCookie(const net::CanonicalCookie& cc) override {}
238 void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override {}
239 void DeleteCookie(const net::CanonicalCookie& cc) override {}
240 void SetForceKeepSessionState() override {}
241 void Flush(const base::Closure& callback) override { flushed_ = true; }
244 ~TestPersistentCookieStore() override {}
246 const GURL kTestCookieURL;
247 LoadedCallback loaded_callback_;
251 // Helper callback to be passed to CookieStore::GetCookiesWithOptionsAsync().
252 class GetCookieCallback {
254 GetCookieCallback() : did_run_(false) {}
256 // Returns true if the callback has been run.
257 bool did_run() { return did_run_; }
259 // Returns the parameter of the callback.
260 const std::string& cookie_line() { return cookie_line_; }
262 void Run(const std::string& cookie_line) {
263 ASSERT_FALSE(did_run_);
265 cookie_line_ = cookie_line;
270 std::string cookie_line_;
273 // Helper callback to be passed to CookieStore::GetAllCookiesForURLAsync().
274 class GetAllCookiesCallback {
276 GetAllCookiesCallback() : did_run_(false) {}
278 // Returns true if the callback has been run.
279 bool did_run() { return did_run_; }
281 // Returns the parameter of the callback.
282 const net::CookieList& cookie_list() { return cookie_list_; }
284 void Run(const net::CookieList& cookie_list) {
285 ASSERT_FALSE(did_run_);
287 cookie_list_ = cookie_list;
292 net::CookieList cookie_list_;
297 void RecordCookieChanges(std::vector<net::CanonicalCookie>* out_cookies,
298 std::vector<bool>* out_removes,
299 const net::CanonicalCookie& cookie,
302 out_cookies->push_back(cookie);
304 out_removes->push_back(removed);
307 void IgnoreBoolean(bool ignored) {
310 void IgnoreString(const std::string& ignored) {
315 class CookieStoreIOSWithBackend : public testing::Test {
317 CookieStoreIOSWithBackend()
318 : kTestCookieURL("http://foo.google.com/bar"),
319 kTestCookieURL2("http://foo.google.com/baz"),
320 kTestCookieURL3("http://foo.google.com"),
321 kTestCookieURL4("http://bar.google.com/bar") {
322 backend_ = new TestPersistentCookieStore;
323 store_ = new net::CookieStoreIOS(backend_.get());
324 net::CookieStoreIOS::SetCookiePolicy(net::CookieStoreIOS::ALLOW);
325 cookie_changed_callback_ = store_->AddCallbackForCookie(
326 kTestCookieURL, "abc",
327 base::Bind(&RecordCookieChanges, &cookies_changed_, &cookies_removed_));
330 ~CookieStoreIOSWithBackend() override {}
332 // Gets the cookies. |callback| will be called on completion.
333 void GetCookies(const net::CookieStore::GetCookiesCallback& callback) {
334 net::CookieOptions options;
335 options.set_include_httponly();
336 store_->GetCookiesWithOptionsAsync(kTestCookieURL, options, callback);
340 void SetCookie(const std::string& cookie_line) {
341 net::CookieOptions options;
342 options.set_include_httponly();
343 store_->SetCookieWithOptionsAsync(kTestCookieURL, cookie_line, options,
344 base::Bind(&IgnoreBoolean));
345 net::CookieStoreIOS::NotifySystemCookiesChanged();
346 // Wait until the flush is posted.
347 base::MessageLoop::current()->RunUntilIdle();
350 void SetSystemCookie(const GURL& url,
351 const std::string& name,
352 const std::string& value) {
353 NSHTTPCookieStorage* storage =
354 [NSHTTPCookieStorage sharedHTTPCookieStorage];
355 [storage setCookie:[NSHTTPCookie cookieWithProperties:@{
356 NSHTTPCookiePath : base::SysUTF8ToNSString(url.path()),
357 NSHTTPCookieName : base::SysUTF8ToNSString(name),
358 NSHTTPCookieValue : base::SysUTF8ToNSString(value),
359 NSHTTPCookieDomain : base::SysUTF8ToNSString(url.host()),
361 net::CookieStoreIOS::NotifySystemCookiesChanged();
362 base::MessageLoop::current()->RunUntilIdle();
365 void DeleteSystemCookie(const GURL& gurl, const std::string& name) {
366 NSHTTPCookieStorage* storage =
367 [NSHTTPCookieStorage sharedHTTPCookieStorage];
368 NSURL* nsurl = net::NSURLWithGURL(gurl);
369 NSArray* cookies = [storage cookiesForURL:nsurl];
370 for (NSHTTPCookie* cookie in cookies) {
371 if (cookie.name.UTF8String == name) {
372 [storage deleteCookie:cookie];
376 net::CookieStoreIOS::NotifySystemCookiesChanged();
377 base::MessageLoop::current()->RunUntilIdle();
381 const GURL kTestCookieURL;
382 const GURL kTestCookieURL2;
383 const GURL kTestCookieURL3;
384 const GURL kTestCookieURL4;
386 base::MessageLoop loop_;
387 scoped_refptr<TestPersistentCookieStore> backend_;
388 scoped_refptr<net::CookieStoreIOS> store_;
389 scoped_ptr<net::CookieStore::CookieChangedSubscription>
390 cookie_changed_callback_;
391 std::vector<net::CanonicalCookie> cookies_changed_;
392 std::vector<bool> cookies_removed_;
399 TEST_F(CookieStoreIOSWithBackend, SetCookieCallsHookWhenNotSynchronized) {
401 SetCookie("abc=def");
402 EXPECT_EQ(0U, cookies_changed_.size());
403 EXPECT_EQ(0U, cookies_removed_.size());
404 backend_->RunLoadedCallback();
405 base::MessageLoop::current()->RunUntilIdle();
406 EXPECT_EQ(1U, cookies_changed_.size());
407 EXPECT_EQ(1U, cookies_removed_.size());
408 EXPECT_EQ("abc", cookies_changed_[0].Name());
409 EXPECT_EQ("def", cookies_changed_[0].Value());
410 EXPECT_FALSE(cookies_removed_[0]);
412 // Replacing an existing cookie is actually a two-phase delete + set
413 // operation, so we get an extra notification.
414 SetCookie("abc=ghi");
415 EXPECT_EQ(3U, cookies_changed_.size());
416 EXPECT_EQ(3U, cookies_removed_.size());
417 EXPECT_EQ("abc", cookies_changed_[1].Name());
418 EXPECT_EQ("def", cookies_changed_[1].Value());
419 EXPECT_TRUE(cookies_removed_[1]);
420 EXPECT_EQ("abc", cookies_changed_[2].Name());
421 EXPECT_EQ("ghi", cookies_changed_[2].Value());
422 EXPECT_FALSE(cookies_removed_[2]);
424 store_->UnSynchronize();
427 TEST_F(CookieStoreIOSWithBackend, SetCookieCallsHookWhenSynchronized) {
428 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
429 GetCookies(base::Bind(&IgnoreString));
430 backend_->RunLoadedCallback();
431 base::MessageLoop::current()->RunUntilIdle();
433 SetCookie("abc=def");
434 EXPECT_EQ(1U, cookies_changed_.size());
435 EXPECT_EQ(1U, cookies_removed_.size());
436 EXPECT_EQ("abc", cookies_changed_[0].Name());
437 EXPECT_EQ("def", cookies_changed_[0].Value());
438 EXPECT_FALSE(cookies_removed_[0]);
440 SetCookie("abc=ghi");
441 EXPECT_EQ(3U, cookies_changed_.size());
442 EXPECT_EQ(3U, cookies_removed_.size());
443 EXPECT_EQ("abc", cookies_changed_[1].Name());
444 EXPECT_EQ("def", cookies_changed_[1].Value());
445 EXPECT_TRUE(cookies_removed_[1]);
446 EXPECT_EQ("abc", cookies_changed_[2].Name());
447 EXPECT_EQ("ghi", cookies_changed_[2].Value());
448 EXPECT_FALSE(cookies_removed_[2]);
449 DeleteSystemCookie(kTestCookieURL, "abc");
451 store_->UnSynchronize();
454 TEST_F(CookieStoreIOSWithBackend, DeleteCallsHook) {
455 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
456 GetCookies(base::Bind(&IgnoreString));
457 backend_->RunLoadedCallback();
458 base::MessageLoop::current()->RunUntilIdle();
460 SetCookie("abc=def");
461 EXPECT_EQ(1U, cookies_changed_.size());
462 EXPECT_EQ(1U, cookies_removed_.size());
463 store_->DeleteCookieAsync(kTestCookieURL, "abc",
464 base::Bind(&IgnoreBoolean, false));
465 CookieStoreIOS::NotifySystemCookiesChanged();
466 base::MessageLoop::current()->RunUntilIdle();
467 store_->UnSynchronize();
470 TEST_F(CookieStoreIOSWithBackend, SameValueDoesNotCallHook) {
471 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
472 GetCookieCallback callback;
473 GetCookies(base::Bind(&IgnoreString));
474 backend_->RunLoadedCallback();
475 base::MessageLoop::current()->RunUntilIdle();
477 SetCookie("abc=def");
478 EXPECT_EQ(1U, cookies_changed_.size());
479 SetCookie("abc=def");
480 EXPECT_EQ(1U, cookies_changed_.size());
481 store_->UnSynchronize();
484 TEST(CookieStoreIOS, GetAllCookiesForURLAsync) {
485 base::MessageLoop loop;
486 const GURL kTestCookieURL("http://foo.google.com/bar");
488 scoped_refptr<CookieStoreIOS> cookie_store(new CookieStoreIOS(nullptr));
489 CookieStoreIOS::SwitchSynchronizedStore(nullptr, cookie_store.get());
491 net::CookieOptions options;
492 options.set_include_httponly();
493 cookie_store->SetCookieWithOptionsAsync(
494 kTestCookieURL, "a=b", options, net::CookieStore::SetCookiesCallback());
496 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
497 // No cookie in the system store.
498 NSHTTPCookieStorage* system_store =
499 [NSHTTPCookieStorage sharedHTTPCookieStorage];
500 EXPECT_EQ(0u, [[system_store cookies] count]);
501 // Flushing should not have any effect.
502 cookie_store->Flush(base::Closure());
503 // Check we can get the cookie even though cookies are disabled.
504 GetAllCookiesCallback callback;
505 cookie_store->GetAllCookiesForURLAsync(
507 base::Bind(&GetAllCookiesCallback::Run, base::Unretained(&callback)));
508 EXPECT_TRUE(callback.did_run());
509 EXPECT_EQ(1u, callback.cookie_list().size());
510 net::CanonicalCookie cookie = callback.cookie_list()[0];
511 EXPECT_EQ("a", cookie.Name());
512 EXPECT_EQ("b", cookie.Value());
513 // Re-enable cookies.
514 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
515 // Cookie is back in the system store.
516 EXPECT_EQ(1u, [[system_store cookies] count]);
517 cookie_store->UnSynchronize();
520 // Tests that cookies can be read before the backend is loaded.
521 TEST_F(CookieStoreIOSWithBackend, NotSynchronized) {
522 // Start fetching the cookie.
523 GetCookieCallback callback;
524 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
525 // Backend loading completes.
526 backend_->RunLoadedCallback();
527 EXPECT_TRUE(callback.did_run());
528 EXPECT_EQ("a=b", callback.cookie_line());
531 // Tests that cookies can be read before synchronization is complete.
532 TEST_F(CookieStoreIOSWithBackend, Synchronizing) {
533 // Start synchronization.
534 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
535 GetCookieCallback callback;
536 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
537 // Backend loading completes (end of synchronization).
538 backend_->RunLoadedCallback();
539 EXPECT_TRUE(callback.did_run());
540 EXPECT_EQ("a=b", callback.cookie_line());
541 store_->UnSynchronize();
544 // Tests that cookies can be read before synchronization is complete, when
545 // triggered by a change in cookie policy.
546 TEST_F(CookieStoreIOSWithBackend, SynchronizingAfterPolicyChange) {
548 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
549 // SwitchSynchronizedStore() does nothing when cookies are blocked.
550 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
551 // Start synchronization by allowing cookies.
552 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
553 GetCookieCallback callback;
554 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
555 // Backend loading completes (end of synchronization).
556 backend_->RunLoadedCallback();
557 EXPECT_TRUE(callback.did_run());
558 EXPECT_EQ("a=b", callback.cookie_line());
559 store_->UnSynchronize();
562 // Tests that Synchronization can be "aborted" (i.e. the cookie store is
563 // unsynchronized while synchronization is in progress).
564 TEST_F(CookieStoreIOSWithBackend, SyncThenUnsync) {
566 scoped_refptr<CookieStoreIOS> dummy_store = new CookieStoreIOS(nullptr);
567 // Switch back and forth before synchronization can complete.
568 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
569 CookieStoreIOS::SwitchSynchronizedStore(store_.get(), dummy_store.get());
570 backend_->RunLoadedCallback();
571 // No cookie leak in the system store.
572 NSHTTPCookieStorage* store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
573 EXPECT_EQ(0u, [[store cookies] count]);
575 GetCookieCallback callback;
576 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
577 EXPECT_TRUE(callback.did_run());
578 EXPECT_EQ("a=b", callback.cookie_line());
579 dummy_store->UnSynchronize();
582 TEST_F(CookieStoreIOSWithBackend, ChangePolicyOnceDuringSynchronization) {
583 // Start synchronization.
584 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
585 // Toggle cookie policy to trigger another synchronization while the first one
586 // is still in progress.
587 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
588 // Backend loading completes (end of synchronization).
589 backend_->RunLoadedCallback();
590 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
591 GetCookieCallback callback;
592 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
593 EXPECT_TRUE(callback.did_run());
594 EXPECT_EQ("a=b", callback.cookie_line());
595 store_->UnSynchronize();
598 TEST_F(CookieStoreIOSWithBackend, ChangePolicyTwiceDuringSynchronization) {
599 // Start synchronization.
600 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
601 // Toggle cookie policy to trigger another synchronization while the first one
602 // is still in progress.
603 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
604 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
605 // Backend loading completes (end of synchronization).
606 backend_->RunLoadedCallback();
607 GetCookieCallback callback;
608 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
609 EXPECT_TRUE(callback.did_run());
610 EXPECT_EQ("a=b", callback.cookie_line());
611 store_->UnSynchronize();
614 TEST_F(CookieStoreIOSWithBackend, UnSynchronizeBeforeLoadComplete) {
616 // Switch back and forth before synchronization can complete.
617 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
618 store_->UnSynchronize();
619 backend_->RunLoadedCallback();
621 GetCookieCallback callback;
622 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
623 EXPECT_TRUE(callback.did_run());
624 EXPECT_EQ("a=b", callback.cookie_line());
627 TEST_F(CookieStoreIOSWithBackend, UnSynchronize) {
629 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
630 backend_->RunLoadedCallback();
631 store_->UnSynchronize();
633 GetCookieCallback callback;
634 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
635 EXPECT_TRUE(callback.did_run());
636 EXPECT_EQ("a=b", callback.cookie_line());
639 TEST_F(CookieStoreIOSWithBackend, FlushOnUnSynchronize) {
640 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
641 EXPECT_FALSE(backend_->flushed());
642 store_->UnSynchronize();
643 EXPECT_TRUE(backend_->flushed());
646 TEST_F(CookieStoreIOSWithBackend, FlushOnSwitch) {
647 scoped_refptr<CookieStoreIOS> dummy_store = new CookieStoreIOS(nullptr);
648 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
649 EXPECT_FALSE(backend_->flushed());
650 CookieStoreIOS::SwitchSynchronizedStore(store_.get(), dummy_store.get());
651 EXPECT_TRUE(backend_->flushed());
652 dummy_store->UnSynchronize();
655 TEST_F(CookieStoreIOSWithBackend, FlushOnCookieChanged) {
656 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
657 store_->set_flush_delay_for_testing(base::TimeDelta());
658 backend_->RunLoadedCallback();
659 EXPECT_FALSE(backend_->flushed());
661 // Set a cookie an check that it triggers a flush.
663 EXPECT_TRUE(backend_->flushed());
665 store_->UnSynchronize();
668 TEST_F(CookieStoreIOSWithBackend, ManualFlush) {
669 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
670 backend_->RunLoadedCallback();
671 EXPECT_FALSE(backend_->flushed());
673 // The store should be flushed even if it is not dirty.
674 store_->Flush(base::Closure());
675 EXPECT_TRUE(backend_->flushed());
677 store_->UnSynchronize();
680 TEST_F(CookieStoreIOSWithBackend, FlushOnPolicyChange) {
681 // Start synchronization.
682 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
683 // Toggle cookie policy to trigger a flush.
684 EXPECT_FALSE(backend_->flushed());
685 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
686 EXPECT_TRUE(backend_->flushed());
687 store_->UnSynchronize();
688 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
691 TEST_F(CookieStoreIOSWithBackend, NoInitialNotifyWithNoCookie) {
692 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
693 std::vector<net::CanonicalCookie> cookies;
694 store_->AddCallbackForCookie(
695 kTestCookieURL, "abc",
696 base::Bind(&RecordCookieChanges, &cookies, nullptr));
697 EXPECT_EQ(0U, cookies.size());
698 store_->UnSynchronize();
701 TEST_F(CookieStoreIOSWithBackend, NoInitialNotifyWithSystemCookie) {
702 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
703 SetSystemCookie(kTestCookieURL, "abc", "def");
704 std::vector<net::CanonicalCookie> cookies;
705 store_->AddCallbackForCookie(
706 kTestCookieURL, "abc",
707 base::Bind(&RecordCookieChanges, &cookies, nullptr));
708 EXPECT_EQ(0U, cookies.size());
709 DeleteSystemCookie(kTestCookieURL, "abc");
710 store_->UnSynchronize();
713 TEST_F(CookieStoreIOSWithBackend, NotifyOnAdd) {
714 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
715 backend_->RunLoadedCallback();
716 std::vector<net::CanonicalCookie> cookies;
717 std::vector<bool> removes;
718 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
719 store_->AddCallbackForCookie(
720 kTestCookieURL, "abc",
721 base::Bind(&RecordCookieChanges, &cookies, &removes));
722 EXPECT_EQ(0U, cookies.size());
723 EXPECT_EQ(0U, removes.size());
724 SetSystemCookie(kTestCookieURL, "abc", "def");
725 EXPECT_EQ(1U, cookies.size());
726 EXPECT_EQ(1U, removes.size());
727 EXPECT_EQ("abc", cookies[0].Name());
728 EXPECT_EQ("def", cookies[0].Value());
729 EXPECT_FALSE(removes[0]);
731 SetSystemCookie(kTestCookieURL, "ghi", "jkl");
732 EXPECT_EQ(1U, cookies.size());
733 EXPECT_EQ(1U, removes.size());
735 DeleteSystemCookie(kTestCookieURL, "abc");
736 DeleteSystemCookie(kTestCookieURL, "ghi");
737 store_->UnSynchronize();
740 TEST_F(CookieStoreIOSWithBackend, NotifyOnChange) {
741 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
742 backend_->RunLoadedCallback();
743 std::vector<net::CanonicalCookie> cookies;
744 std::vector<bool> removes;
745 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
746 store_->AddCallbackForCookie(
747 kTestCookieURL, "abc",
748 base::Bind(&RecordCookieChanges, &cookies, &removes));
749 EXPECT_EQ(0U, cookies.size());
750 SetSystemCookie(kTestCookieURL, "abc", "def");
751 EXPECT_EQ(1U, cookies.size());
752 SetSystemCookie(kTestCookieURL, "abc", "ghi");
753 EXPECT_EQ(3U, cookies.size());
754 EXPECT_EQ(3U, removes.size());
755 EXPECT_EQ("abc", cookies[1].Name());
756 EXPECT_EQ("def", cookies[1].Value());
757 EXPECT_TRUE(removes[1]);
758 EXPECT_EQ("abc", cookies[2].Name());
759 EXPECT_EQ("ghi", cookies[2].Value());
760 EXPECT_FALSE(removes[2]);
762 DeleteSystemCookie(kTestCookieURL, "abc");
763 store_->UnSynchronize();
766 TEST_F(CookieStoreIOSWithBackend, NotifyOnDelete) {
767 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
768 backend_->RunLoadedCallback();
769 std::vector<net::CanonicalCookie> cookies;
770 std::vector<bool> removes;
771 SetSystemCookie(kTestCookieURL, "abc", "def");
772 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
773 store_->AddCallbackForCookie(
774 kTestCookieURL, "abc",
775 base::Bind(&RecordCookieChanges, &cookies, &removes));
776 EXPECT_EQ(0U, cookies.size());
777 DeleteSystemCookie(kTestCookieURL, "abc");
778 EXPECT_EQ(1U, cookies.size());
779 EXPECT_EQ(1U, removes.size());
780 EXPECT_TRUE(removes[0]);
781 SetSystemCookie(kTestCookieURL, "abc", "def");
782 EXPECT_EQ(2U, cookies.size());
783 EXPECT_EQ(2U, removes.size());
784 EXPECT_FALSE(removes[1]);
785 DeleteSystemCookie(kTestCookieURL, "abc");
786 store_->UnSynchronize();
789 TEST_F(CookieStoreIOSWithBackend, NoNotifyOnNoChange) {
790 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
791 backend_->RunLoadedCallback();
792 std::vector<net::CanonicalCookie> cookies;
793 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
794 store_->AddCallbackForCookie(
795 kTestCookieURL, "abc",
796 base::Bind(&RecordCookieChanges, &cookies, nullptr));
797 EXPECT_EQ(0U, cookies.size());
798 SetSystemCookie(kTestCookieURL, "abc", "def");
799 EXPECT_EQ(1U, cookies.size());
800 SetSystemCookie(kTestCookieURL, "abc", "def");
801 EXPECT_EQ(1U, cookies.size());
802 DeleteSystemCookie(kTestCookieURL, "abc");
803 store_->UnSynchronize();
806 TEST_F(CookieStoreIOSWithBackend, MultipleNotifies) {
807 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
808 backend_->RunLoadedCallback();
809 std::vector<net::CanonicalCookie> cookies;
810 std::vector<net::CanonicalCookie> cookies2;
811 std::vector<net::CanonicalCookie> cookies3;
812 std::vector<net::CanonicalCookie> cookies4;
813 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
814 store_->AddCallbackForCookie(
815 kTestCookieURL, "abc",
816 base::Bind(&RecordCookieChanges, &cookies, nullptr));
817 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle2 =
818 store_->AddCallbackForCookie(
819 kTestCookieURL2, "abc",
820 base::Bind(&RecordCookieChanges, &cookies2, nullptr));
821 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle3 =
822 store_->AddCallbackForCookie(
823 kTestCookieURL3, "abc",
824 base::Bind(&RecordCookieChanges, &cookies3, nullptr));
825 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle4 =
826 store_->AddCallbackForCookie(
827 kTestCookieURL4, "abc",
828 base::Bind(&RecordCookieChanges, &cookies4, nullptr));
829 SetSystemCookie(kTestCookieURL, "abc", "def");
830 SetSystemCookie(kTestCookieURL2, "abc", "def");
831 SetSystemCookie(kTestCookieURL3, "abc", "def");
832 SetSystemCookie(kTestCookieURL4, "abc", "def");
833 EXPECT_EQ(2U, cookies.size());
834 EXPECT_EQ(2U, cookies2.size());
835 EXPECT_EQ(1U, cookies3.size());
836 EXPECT_EQ(1U, cookies4.size());
837 DeleteSystemCookie(kTestCookieURL, "abc");
838 DeleteSystemCookie(kTestCookieURL2, "abc");
839 DeleteSystemCookie(kTestCookieURL3, "abc");
840 DeleteSystemCookie(kTestCookieURL4, "abc");
841 store_->UnSynchronize();
844 TEST_F(CookieStoreIOSWithBackend, LessSpecificNestedCookie) {
845 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
846 backend_->RunLoadedCallback();
847 std::vector<net::CanonicalCookie> cookies;
848 SetSystemCookie(kTestCookieURL2, "abc", "def");
849 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
850 store_->AddCallbackForCookie(
851 kTestCookieURL2, "abc",
852 base::Bind(&RecordCookieChanges, &cookies, nullptr));
853 EXPECT_EQ(0U, cookies.size());
854 SetSystemCookie(kTestCookieURL3, "abc", "ghi");
855 EXPECT_EQ(1U, cookies.size());
856 DeleteSystemCookie(kTestCookieURL, "abc");
857 store_->UnSynchronize();
860 TEST_F(CookieStoreIOSWithBackend, MoreSpecificNestedCookie) {
861 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
862 backend_->RunLoadedCallback();
863 std::vector<net::CanonicalCookie> cookies;
864 SetSystemCookie(kTestCookieURL3, "abc", "def");
865 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
866 store_->AddCallbackForCookie(
867 kTestCookieURL2, "abc",
868 base::Bind(&RecordCookieChanges, &cookies, nullptr));
869 EXPECT_EQ(0U, cookies.size());
870 SetSystemCookie(kTestCookieURL2, "abc", "ghi");
871 EXPECT_EQ(1U, cookies.size());
872 DeleteSystemCookie(kTestCookieURL, "abc");
873 store_->UnSynchronize();
876 TEST_F(CookieStoreIOSWithBackend, MoreSpecificNestedCookieWithSameValue) {
877 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
878 backend_->RunLoadedCallback();
879 std::vector<net::CanonicalCookie> cookies;
880 SetSystemCookie(kTestCookieURL3, "abc", "def");
881 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
882 store_->AddCallbackForCookie(
883 kTestCookieURL2, "abc",
884 base::Bind(&RecordCookieChanges, &cookies, nullptr));
885 EXPECT_EQ(0U, cookies.size());
886 SetSystemCookie(kTestCookieURL2, "abc", "def");
887 EXPECT_EQ(1U, cookies.size());
888 DeleteSystemCookie(kTestCookieURL, "abc");
889 store_->UnSynchronize();
892 TEST_F(CookieStoreIOSWithBackend, RemoveCallback) {
893 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
894 backend_->RunLoadedCallback();
895 std::vector<net::CanonicalCookie> cookies;
896 SetSystemCookie(kTestCookieURL, "abc", "def");
897 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
898 store_->AddCallbackForCookie(
899 kTestCookieURL, "abc",
900 base::Bind(&RecordCookieChanges, &cookies, nullptr));
901 EXPECT_EQ(0U, cookies.size());
902 SetSystemCookie(kTestCookieURL, "abc", "ghi");
903 EXPECT_EQ(2U, cookies.size());
904 // this deletes the callback
906 SetSystemCookie(kTestCookieURL, "abc", "jkl");
907 EXPECT_EQ(2U, cookies.size());
908 DeleteSystemCookie(kTestCookieURL, "abc");
909 store_->UnSynchronize();