// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/files/file_util.h" #include "base/test/bind.h" #include "build/build_config.h" #include "content/public/browser/browser_context.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "weblayer/browser/cookie_manager_impl.h" #include "weblayer/browser/profile_impl.h" #include "weblayer/public/cookie_manager.h" #include "weblayer/test/weblayer_browser_test.h" #include "weblayer/test/weblayer_browser_test_utils.h" namespace weblayer { class CookieManagerBrowserTest : public WebLayerBrowserTest { public: const std::vector& WaitForChanges(size_t num) { if (change_infos_.size() >= num) return change_infos_; num_to_wait_for_ = num; run_loop_ = std::make_unique(); run_loop_->Run(); return change_infos_; } void OnCookieChanged(const net::CookieChangeInfo& info) { change_infos_.push_back(info); if (run_loop_ && num_to_wait_for_ == change_infos_.size()) run_loop_->Quit(); } void Reset() { change_infos_.clear(); } bool SetCookie(const std::string& cookie) { GURL base_url = embedded_test_server()->base_url(); base::RunLoop run_loop; bool final_result = false; GetProfile()->GetCookieManager()->SetCookie( base_url, cookie, base::BindLambdaForTesting([&run_loop, &final_result](bool result) { final_result = result; run_loop.Quit(); })); run_loop.Run(); return final_result; } base::Time GetCookieDbModifiedTime() { base::FilePath cookie_path = GetBrowserContext()->GetPath().Append(FILE_PATH_LITERAL("Cookies")); base::ScopedAllowBlockingForTesting scoped_allow_blocking; base::File::Info info; EXPECT_TRUE(base::GetFileInfo(cookie_path, &info)); return info.last_modified; } private: size_t num_to_wait_for_ = 0; std::vector change_infos_; std::unique_ptr run_loop_; }; IN_PROC_BROWSER_TEST_F(CookieManagerBrowserTest, CookieChanged) { EXPECT_TRUE(embedded_test_server()->Start()); NavigateAndWaitForCompletion( embedded_test_server()->GetURL("/simple_page.html"), shell()); GURL base_url = embedded_test_server()->base_url(); base::CallbackListSubscription subscription = GetProfile()->GetCookieManager()->AddCookieChangedCallback( base_url, nullptr, base::BindRepeating(&CookieManagerBrowserTest::OnCookieChanged, base::Unretained(this))); ASSERT_TRUE(SetCookie("foo=bar")); const auto& changes = WaitForChanges(1); ASSERT_EQ(changes.size(), 1u); const auto& cookie = changes[0].cookie; EXPECT_EQ(cookie.Name(), "foo"); EXPECT_EQ(cookie.Value(), "bar"); } IN_PROC_BROWSER_TEST_F(CookieManagerBrowserTest, CookieChangedRemoveSubscription) { EXPECT_TRUE(embedded_test_server()->Start()); NavigateAndWaitForCompletion( embedded_test_server()->GetURL("/simple_page.html"), shell()); GURL base_url = embedded_test_server()->base_url(); std::string cookie1 = "cookie1"; base::CallbackListSubscription subscription1 = GetProfile()->GetCookieManager()->AddCookieChangedCallback( base_url, &cookie1, base::BindRepeating(&CookieManagerBrowserTest::OnCookieChanged, base::Unretained(this))); std::string cookie2 = "cookie2"; base::CallbackListSubscription subscription2 = GetProfile()->GetCookieManager()->AddCookieChangedCallback( base_url, &cookie2, base::BindRepeating(&CookieManagerBrowserTest::OnCookieChanged, base::Unretained(this))); ASSERT_TRUE(SetCookie("cookie1=something")); { const auto& changes = WaitForChanges(1); ASSERT_EQ(changes.size(), 1u); EXPECT_EQ(changes[0].cookie.Name(), cookie1); } Reset(); subscription1 = {}; // Set cookie1 first and then cookie2. We should only receive a cookie change // event for cookie2. ASSERT_TRUE(SetCookie("cookie1=other")); ASSERT_TRUE(SetCookie("cookie2=something")); { const auto& changes = WaitForChanges(1); ASSERT_EQ(changes.size(), 1u); EXPECT_EQ(changes[0].cookie.Name(), cookie2); } } #if BUILDFLAG(IS_WIN) // TODO(crbug.com/1204901): Disabled due to flakiness on Windows. #define MAYBE_FlushCookiesAfterSet DISABLED_FlushCookiesAfterSet #else #define MAYBE_FlushCookiesAfterSet FlushCookiesAfterSet #endif IN_PROC_BROWSER_TEST_F(CookieManagerBrowserTest, MAYBE_FlushCookiesAfterSet) { EXPECT_TRUE(embedded_test_server()->Start()); NavigateAndWaitForCompletion( embedded_test_server()->GetURL("/simple_page.html"), shell()); base::Time original_modified_time = GetCookieDbModifiedTime(); ASSERT_TRUE(SetCookie("a=b; expires=Fri, 01 Jan 2038 00:00:00 GMT")); EXPECT_EQ(GetCookieDbModifiedTime(), original_modified_time); EXPECT_TRUE(static_cast(GetProfile()->GetCookieManager()) ->FireFlushTimerForTesting()); EXPECT_GT(GetCookieDbModifiedTime(), original_modified_time); } #if BUILDFLAG(IS_WIN) // TODO(crbug.com/1204901): Disabled due to flakiness on Windows. #define MAYBE_FlushCookiesAfterSetMultiple DISABLED_FlushCookiesAfterSetMultiple #else #define MAYBE_FlushCookiesAfterSetMultiple FlushCookiesAfterSetMultiple #endif IN_PROC_BROWSER_TEST_F(CookieManagerBrowserTest, MAYBE_FlushCookiesAfterSetMultiple) { EXPECT_TRUE(embedded_test_server()->Start()); NavigateAndWaitForCompletion( embedded_test_server()->GetURL("/simple_page.html"), shell()); base::Time original_modified_time = GetCookieDbModifiedTime(); ASSERT_TRUE(SetCookie("a=b; expires=Fri, 01 Jan 2038 00:00:00 GMT")); EXPECT_EQ(GetCookieDbModifiedTime(), original_modified_time); ASSERT_TRUE(SetCookie("c=d; expires=Fri, 01 Jan 2038 00:00:00 GMT")); EXPECT_EQ(GetCookieDbModifiedTime(), original_modified_time); CookieManagerImpl* cookie_manager = static_cast(GetProfile()->GetCookieManager()); EXPECT_TRUE(cookie_manager->FireFlushTimerForTesting()); EXPECT_GT(GetCookieDbModifiedTime(), original_modified_time); // Flush timer should be gone now. EXPECT_FALSE(cookie_manager->FireFlushTimerForTesting()); // Try again to make sure it works a second time. original_modified_time = GetCookieDbModifiedTime(); ASSERT_TRUE(SetCookie("d=f; expires=Fri, 01 Jan 2038 00:00:00 GMT")); EXPECT_EQ(GetCookieDbModifiedTime(), original_modified_time); EXPECT_TRUE(cookie_manager->FireFlushTimerForTesting()); EXPECT_GT(GetCookieDbModifiedTime(), original_modified_time); } } // namespace weblayer