| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/components/cookie_util/cookie_util.h" |
| |
| #import <Foundation/Foundation.h> |
| #import <stddef.h> |
| #import <stdint.h> |
| #import <sys/sysctl.h> |
| |
| #import "base/check.h" |
| #import "base/functional/bind.h" |
| #import "base/functional/callback_helpers.h" |
| #import "base/memory/ref_counted.h" |
| #import "base/task/thread_pool.h" |
| #import "components/prefs/pref_service.h" |
| #import "ios/components/cookie_util/cookie_constants.h" |
| #import "ios/net/cookies/cookie_store_ios.h" |
| #import "ios/net/cookies/system_cookie_store.h" |
| #import "ios/web/common/features.h" |
| #import "ios/web/public/browser_state.h" |
| #import "ios/web/public/thread/web_task_traits.h" |
| #import "ios/web/public/thread/web_thread.h" |
| #import "net/cookies/cookie_monster.h" |
| #import "net/cookies/cookie_store.h" |
| #import "net/extras/sqlite/sqlite_persistent_cookie_store.h" |
| #import "net/log/net_log.h" |
| #import "net/url_request/url_request_context.h" |
| #import "net/url_request/url_request_context_getter.h" |
| |
| namespace cookie_util { |
| |
| namespace { |
| |
| // Creates a SQLitePersistentCookieStore running on a background thread. |
| scoped_refptr<net::SQLitePersistentCookieStore> CreatePersistentCookieStore( |
| const base::FilePath& path, |
| bool restore_old_session_cookies) { |
| return scoped_refptr<net::SQLitePersistentCookieStore>( |
| new net::SQLitePersistentCookieStore( |
| path, web::GetIOThreadTaskRunner({}), |
| base::ThreadPool::CreateSequencedTaskRunner( |
| {base::MayBlock(), base::TaskPriority::BEST_EFFORT, |
| base::TaskShutdownBehavior::BLOCK_SHUTDOWN}), |
| restore_old_session_cookies, /*crypto_delegate=*/nullptr, |
| /*enable_exclusive_access=*/false)); |
| } |
| |
| // Creates a CookieMonster configured by `config`. |
| std::unique_ptr<net::CookieMonster> CreateCookieMonster( |
| const CookieStoreConfig& config, |
| net::NetLog* net_log) { |
| if (config.path.empty()) { |
| // Empty path means in-memory store. |
| return std::make_unique<net::CookieMonster>(nullptr /* store */, net_log); |
| } |
| |
| const bool restore_old_session_cookies = |
| config.session_cookie_mode == CookieStoreConfig::RESTORED_SESSION_COOKIES; |
| scoped_refptr<net::SQLitePersistentCookieStore> persistent_store = |
| CreatePersistentCookieStore(config.path, restore_old_session_cookies); |
| std::unique_ptr<net::CookieMonster> cookie_monster( |
| new net::CookieMonster(persistent_store.get(), net_log)); |
| if (restore_old_session_cookies) { |
| cookie_monster->SetPersistSessionCookies(true); |
| } |
| return cookie_monster; |
| } |
| |
| } // namespace |
| |
| CookieStoreConfig::CookieStoreConfig(const base::FilePath& path, |
| SessionCookieMode session_cookie_mode, |
| CookieStoreType cookie_store_type) |
| : path(path), |
| session_cookie_mode(session_cookie_mode), |
| cookie_store_type(cookie_store_type) { |
| CHECK(!path.empty() || session_cookie_mode == EPHEMERAL_SESSION_COOKIES); |
| } |
| |
| CookieStoreConfig::~CookieStoreConfig() {} |
| |
| std::unique_ptr<net::CookieStore> CreateCookieStore( |
| const CookieStoreConfig& config, |
| std::unique_ptr<net::SystemCookieStore> system_cookie_store, |
| net::NetLog* net_log) { |
| if (config.cookie_store_type == CookieStoreConfig::COOKIE_MONSTER) { |
| return CreateCookieMonster(config, net_log); |
| } |
| |
| // Using the SystemCookieStore will allow URLFetcher and any other users of |
| // net:CookieStore to in iOS to use cookies directly from WKHTTPCookieStore. |
| return std::make_unique<net::CookieStoreIOS>(std::move(system_cookie_store), |
| net_log); |
| } |
| |
| bool ShouldClearSessionCookies(PrefService* pref_service) { |
| const base::Time last_cookie_deletion_date = |
| pref_service->GetTime(kLastCookieDeletionDate); |
| |
| bool clear_cookies = true; |
| if (!last_cookie_deletion_date.is_null()) { |
| struct timeval boottime; |
| int mib[2] = {CTL_KERN, KERN_BOOTTIME}; |
| size_t size = sizeof(boottime); |
| |
| if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) { |
| if (boottime.tv_sec != 0) { |
| const base::Time boot = base::Time::FromTimeVal(boottime); |
| |
| clear_cookies = boot > last_cookie_deletion_date; |
| } |
| } |
| } |
| if (clear_cookies) { |
| pref_service->SetTime(kLastCookieDeletionDate, base::Time::Now()); |
| } |
| return clear_cookies; |
| } |
| |
| // Clears the session cookies for `browser_state`. |
| void ClearSessionCookies(web::BrowserState* browser_state) { |
| scoped_refptr<net::URLRequestContextGetter> getter = |
| browser_state->GetRequestContext(); |
| web::GetIOThreadTaskRunner({})->PostTask( |
| FROM_HERE, base::BindOnce(^{ |
| net::CookieStore* cookie_store = |
| getter->GetURLRequestContext()->cookie_store(); |
| if (cookie_store) { |
| cookie_store->DeleteSessionCookiesAsync(base::DoNothing()); |
| } |
| })); |
| } |
| |
| } // namespace cookie_util |