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 preserves_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 preserves_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 preserves_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 // Tests that Synchronization can be "aborted" while there are pending tasks
583 // (i.e. the cookie store is unsynchronized while synchronization is in progress
584 // and there are pending tasks).
585 TEST_F(CookieStoreIOSWithBackend, SyncThenUnsyncWithPendingTasks) {
587 scoped_refptr<CookieStoreIOS> dummy_store = new CookieStoreIOS(nullptr);
588 // Start synchornization.
589 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
590 // Create a pending task while synchronization is in progress.
591 GetCookieCallback callback;
592 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
593 // Cancel the synchronization.
594 CookieStoreIOS::SwitchSynchronizedStore(store_.get(), dummy_store.get());
595 // Synchronization completes after being cancelled.
596 backend_->RunLoadedCallback();
597 // The task is not lost.
598 EXPECT_TRUE(callback.did_run());
599 EXPECT_EQ("a=b", callback.cookie_line());
600 dummy_store->UnSynchronize();
603 TEST_F(CookieStoreIOSWithBackend, ChangePolicyOnceDuringSynchronization) {
604 // Start synchronization.
605 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
606 // Toggle cookie policy to trigger another synchronization while the first one
607 // is still in progress.
608 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
609 // Backend loading completes (end of synchronization).
610 backend_->RunLoadedCallback();
611 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
612 GetCookieCallback callback;
613 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
614 EXPECT_TRUE(callback.did_run());
615 EXPECT_EQ("a=b", callback.cookie_line());
616 store_->UnSynchronize();
619 TEST_F(CookieStoreIOSWithBackend,
620 ChangePolicyDuringSynchronizationWithPendingTask) {
621 // Start synchronization.
622 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
623 // Create a pending task while synchronization is in progress.
624 GetCookieCallback callback;
625 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
626 // Toggle cookie policy to trigger another synchronization while the first one
627 // is still in progress.
628 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
629 // Backend loading completes (end of synchronization).
630 backend_->RunLoadedCallback();
631 EXPECT_TRUE(callback.did_run());
632 EXPECT_EQ("a=b", callback.cookie_line());
633 store_->UnSynchronize();
636 TEST_F(CookieStoreIOSWithBackend, ChangePolicyTwiceDuringSynchronization) {
637 // Start synchronization.
638 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
639 // Toggle cookie policy to trigger another synchronization while the first one
640 // is still in progress.
641 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
642 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
643 // Backend loading completes (end of synchronization).
644 backend_->RunLoadedCallback();
645 GetCookieCallback callback;
646 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
647 EXPECT_TRUE(callback.did_run());
648 EXPECT_EQ("a=b", callback.cookie_line());
649 store_->UnSynchronize();
652 TEST_F(CookieStoreIOSWithBackend, UnSynchronizeBeforeLoadComplete) {
654 // Switch back and forth before synchronization can complete.
655 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
656 store_->UnSynchronize();
657 backend_->RunLoadedCallback();
659 GetCookieCallback callback;
660 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
661 EXPECT_TRUE(callback.did_run());
662 EXPECT_EQ("a=b", callback.cookie_line());
665 TEST_F(CookieStoreIOSWithBackend, UnSynchronize) {
667 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
668 backend_->RunLoadedCallback();
669 store_->UnSynchronize();
671 GetCookieCallback callback;
672 GetCookies(base::Bind(&GetCookieCallback::Run, base::Unretained(&callback)));
673 EXPECT_TRUE(callback.did_run());
674 EXPECT_EQ("a=b", callback.cookie_line());
677 TEST_F(CookieStoreIOSWithBackend, FlushOnUnSynchronize) {
678 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
679 EXPECT_FALSE(backend_->flushed());
680 store_->UnSynchronize();
681 EXPECT_TRUE(backend_->flushed());
684 TEST_F(CookieStoreIOSWithBackend, FlushOnSwitch) {
685 scoped_refptr<CookieStoreIOS> dummy_store = new CookieStoreIOS(nullptr);
686 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
687 EXPECT_FALSE(backend_->flushed());
688 CookieStoreIOS::SwitchSynchronizedStore(store_.get(), dummy_store.get());
689 EXPECT_TRUE(backend_->flushed());
690 dummy_store->UnSynchronize();
693 TEST_F(CookieStoreIOSWithBackend, FlushOnCookieChanged) {
694 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
695 store_->set_flush_delay_for_testing(base::TimeDelta());
696 backend_->RunLoadedCallback();
697 EXPECT_FALSE(backend_->flushed());
699 // Set a cookie an check that it triggers a flush.
701 EXPECT_TRUE(backend_->flushed());
703 store_->UnSynchronize();
706 TEST_F(CookieStoreIOSWithBackend, ManualFlush) {
707 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
708 backend_->RunLoadedCallback();
709 EXPECT_FALSE(backend_->flushed());
711 // The store should be flushed even if it is not dirty.
712 store_->Flush(base::Closure());
713 EXPECT_TRUE(backend_->flushed());
715 store_->UnSynchronize();
718 TEST_F(CookieStoreIOSWithBackend, FlushOnPolicyChange) {
719 // Start synchronization.
720 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
721 // Toggle cookie policy to trigger a flush.
722 EXPECT_FALSE(backend_->flushed());
723 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::BLOCK);
724 EXPECT_TRUE(backend_->flushed());
725 store_->UnSynchronize();
726 CookieStoreIOS::SetCookiePolicy(CookieStoreIOS::ALLOW);
729 TEST_F(CookieStoreIOSWithBackend, NoInitialNotifyWithNoCookie) {
730 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
731 std::vector<net::CanonicalCookie> cookies;
732 store_->AddCallbackForCookie(
733 kTestCookieURL, "abc",
734 base::Bind(&RecordCookieChanges, &cookies, nullptr));
735 EXPECT_EQ(0U, cookies.size());
736 store_->UnSynchronize();
739 TEST_F(CookieStoreIOSWithBackend, NoInitialNotifyWithSystemCookie) {
740 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
741 SetSystemCookie(kTestCookieURL, "abc", "def");
742 std::vector<net::CanonicalCookie> cookies;
743 store_->AddCallbackForCookie(
744 kTestCookieURL, "abc",
745 base::Bind(&RecordCookieChanges, &cookies, nullptr));
746 EXPECT_EQ(0U, cookies.size());
747 DeleteSystemCookie(kTestCookieURL, "abc");
748 store_->UnSynchronize();
751 TEST_F(CookieStoreIOSWithBackend, NotifyOnAdd) {
752 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
753 backend_->RunLoadedCallback();
754 std::vector<net::CanonicalCookie> cookies;
755 std::vector<bool> removes;
756 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
757 store_->AddCallbackForCookie(
758 kTestCookieURL, "abc",
759 base::Bind(&RecordCookieChanges, &cookies, &removes));
760 EXPECT_EQ(0U, cookies.size());
761 EXPECT_EQ(0U, removes.size());
762 SetSystemCookie(kTestCookieURL, "abc", "def");
763 EXPECT_EQ(1U, cookies.size());
764 EXPECT_EQ(1U, removes.size());
765 EXPECT_EQ("abc", cookies[0].Name());
766 EXPECT_EQ("def", cookies[0].Value());
767 EXPECT_FALSE(removes[0]);
769 SetSystemCookie(kTestCookieURL, "ghi", "jkl");
770 EXPECT_EQ(1U, cookies.size());
771 EXPECT_EQ(1U, removes.size());
773 DeleteSystemCookie(kTestCookieURL, "abc");
774 DeleteSystemCookie(kTestCookieURL, "ghi");
775 store_->UnSynchronize();
778 TEST_F(CookieStoreIOSWithBackend, NotifyOnChange) {
779 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
780 backend_->RunLoadedCallback();
781 std::vector<net::CanonicalCookie> cookies;
782 std::vector<bool> removes;
783 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
784 store_->AddCallbackForCookie(
785 kTestCookieURL, "abc",
786 base::Bind(&RecordCookieChanges, &cookies, &removes));
787 EXPECT_EQ(0U, cookies.size());
788 SetSystemCookie(kTestCookieURL, "abc", "def");
789 EXPECT_EQ(1U, cookies.size());
790 SetSystemCookie(kTestCookieURL, "abc", "ghi");
791 EXPECT_EQ(3U, cookies.size());
792 EXPECT_EQ(3U, removes.size());
793 EXPECT_EQ("abc", cookies[1].Name());
794 EXPECT_EQ("def", cookies[1].Value());
795 EXPECT_TRUE(removes[1]);
796 EXPECT_EQ("abc", cookies[2].Name());
797 EXPECT_EQ("ghi", cookies[2].Value());
798 EXPECT_FALSE(removes[2]);
800 DeleteSystemCookie(kTestCookieURL, "abc");
801 store_->UnSynchronize();
804 TEST_F(CookieStoreIOSWithBackend, NotifyOnDelete) {
805 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
806 backend_->RunLoadedCallback();
807 std::vector<net::CanonicalCookie> cookies;
808 std::vector<bool> removes;
809 SetSystemCookie(kTestCookieURL, "abc", "def");
810 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
811 store_->AddCallbackForCookie(
812 kTestCookieURL, "abc",
813 base::Bind(&RecordCookieChanges, &cookies, &removes));
814 EXPECT_EQ(0U, cookies.size());
815 DeleteSystemCookie(kTestCookieURL, "abc");
816 EXPECT_EQ(1U, cookies.size());
817 EXPECT_EQ(1U, removes.size());
818 EXPECT_TRUE(removes[0]);
819 SetSystemCookie(kTestCookieURL, "abc", "def");
820 EXPECT_EQ(2U, cookies.size());
821 EXPECT_EQ(2U, removes.size());
822 EXPECT_FALSE(removes[1]);
823 DeleteSystemCookie(kTestCookieURL, "abc");
824 store_->UnSynchronize();
827 TEST_F(CookieStoreIOSWithBackend, NoNotifyOnNoChange) {
828 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
829 backend_->RunLoadedCallback();
830 std::vector<net::CanonicalCookie> cookies;
831 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
832 store_->AddCallbackForCookie(
833 kTestCookieURL, "abc",
834 base::Bind(&RecordCookieChanges, &cookies, nullptr));
835 EXPECT_EQ(0U, cookies.size());
836 SetSystemCookie(kTestCookieURL, "abc", "def");
837 EXPECT_EQ(1U, cookies.size());
838 SetSystemCookie(kTestCookieURL, "abc", "def");
839 EXPECT_EQ(1U, cookies.size());
840 DeleteSystemCookie(kTestCookieURL, "abc");
841 store_->UnSynchronize();
844 TEST_F(CookieStoreIOSWithBackend, MultipleNotifies) {
845 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
846 backend_->RunLoadedCallback();
847 std::vector<net::CanonicalCookie> cookies;
848 std::vector<net::CanonicalCookie> cookies2;
849 std::vector<net::CanonicalCookie> cookies3;
850 std::vector<net::CanonicalCookie> cookies4;
851 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
852 store_->AddCallbackForCookie(
853 kTestCookieURL, "abc",
854 base::Bind(&RecordCookieChanges, &cookies, nullptr));
855 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle2 =
856 store_->AddCallbackForCookie(
857 kTestCookieURL2, "abc",
858 base::Bind(&RecordCookieChanges, &cookies2, nullptr));
859 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle3 =
860 store_->AddCallbackForCookie(
861 kTestCookieURL3, "abc",
862 base::Bind(&RecordCookieChanges, &cookies3, nullptr));
863 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle4 =
864 store_->AddCallbackForCookie(
865 kTestCookieURL4, "abc",
866 base::Bind(&RecordCookieChanges, &cookies4, nullptr));
867 SetSystemCookie(kTestCookieURL, "abc", "def");
868 SetSystemCookie(kTestCookieURL2, "abc", "def");
869 SetSystemCookie(kTestCookieURL3, "abc", "def");
870 SetSystemCookie(kTestCookieURL4, "abc", "def");
871 EXPECT_EQ(2U, cookies.size());
872 EXPECT_EQ(2U, cookies2.size());
873 EXPECT_EQ(1U, cookies3.size());
874 EXPECT_EQ(1U, cookies4.size());
875 DeleteSystemCookie(kTestCookieURL, "abc");
876 DeleteSystemCookie(kTestCookieURL2, "abc");
877 DeleteSystemCookie(kTestCookieURL3, "abc");
878 DeleteSystemCookie(kTestCookieURL4, "abc");
879 store_->UnSynchronize();
882 TEST_F(CookieStoreIOSWithBackend, LessSpecificNestedCookie) {
883 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
884 backend_->RunLoadedCallback();
885 std::vector<net::CanonicalCookie> cookies;
886 SetSystemCookie(kTestCookieURL2, "abc", "def");
887 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
888 store_->AddCallbackForCookie(
889 kTestCookieURL2, "abc",
890 base::Bind(&RecordCookieChanges, &cookies, nullptr));
891 EXPECT_EQ(0U, cookies.size());
892 SetSystemCookie(kTestCookieURL3, "abc", "ghi");
893 EXPECT_EQ(1U, cookies.size());
894 DeleteSystemCookie(kTestCookieURL, "abc");
895 store_->UnSynchronize();
898 TEST_F(CookieStoreIOSWithBackend, MoreSpecificNestedCookie) {
899 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
900 backend_->RunLoadedCallback();
901 std::vector<net::CanonicalCookie> cookies;
902 SetSystemCookie(kTestCookieURL3, "abc", "def");
903 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
904 store_->AddCallbackForCookie(
905 kTestCookieURL2, "abc",
906 base::Bind(&RecordCookieChanges, &cookies, nullptr));
907 EXPECT_EQ(0U, cookies.size());
908 SetSystemCookie(kTestCookieURL2, "abc", "ghi");
909 EXPECT_EQ(1U, cookies.size());
910 DeleteSystemCookie(kTestCookieURL, "abc");
911 store_->UnSynchronize();
914 TEST_F(CookieStoreIOSWithBackend, MoreSpecificNestedCookieWithSameValue) {
915 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
916 backend_->RunLoadedCallback();
917 std::vector<net::CanonicalCookie> cookies;
918 SetSystemCookie(kTestCookieURL3, "abc", "def");
919 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
920 store_->AddCallbackForCookie(
921 kTestCookieURL2, "abc",
922 base::Bind(&RecordCookieChanges, &cookies, nullptr));
923 EXPECT_EQ(0U, cookies.size());
924 SetSystemCookie(kTestCookieURL2, "abc", "def");
925 EXPECT_EQ(1U, cookies.size());
926 DeleteSystemCookie(kTestCookieURL, "abc");
927 store_->UnSynchronize();
930 TEST_F(CookieStoreIOSWithBackend, RemoveCallback) {
931 CookieStoreIOS::SwitchSynchronizedStore(nullptr, store_.get());
932 backend_->RunLoadedCallback();
933 std::vector<net::CanonicalCookie> cookies;
934 SetSystemCookie(kTestCookieURL, "abc", "def");
935 scoped_ptr<net::CookieStore::CookieChangedSubscription> handle =
936 store_->AddCallbackForCookie(
937 kTestCookieURL, "abc",
938 base::Bind(&RecordCookieChanges, &cookies, nullptr));
939 EXPECT_EQ(0U, cookies.size());
940 SetSystemCookie(kTestCookieURL, "abc", "ghi");
941 EXPECT_EQ(2U, cookies.size());
942 // this deletes the callback
944 SetSystemCookie(kTestCookieURL, "abc", "jkl");
945 EXPECT_EQ(2U, cookies.size());
946 DeleteSystemCookie(kTestCookieURL, "abc");
947 store_->UnSynchronize();