blob: 7582d21bc8e67f65db8bc999814584c6b1241640 [file] [log] [blame]
// Copyright 2012 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 "ios/chrome/browser/net/cookie_util.h"
#import <Foundation/Foundation.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/sysctl.h>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/task/post_task.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/net/cookies/cookie_store_ios_persistent.h"
#import "ios/net/cookies/system_cookie_store.h"
#include "ios/web/public/features.h"
#include "ios/web/public/web_task_traits.h"
#include "ios/web/public/web_thread.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
#include "net/log/net_log.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace cookie_util {
namespace {
// Date of the last cookie deletion.
NSString* const kLastCookieDeletionDate = @"LastCookieDeletionDate";
// Creates a SQLitePersistentCookieStore running on a background thread.
scoped_refptr<net::SQLitePersistentCookieStore> CreatePersistentCookieStore(
const base::FilePath& path,
bool restore_old_session_cookies,
net::CookieCryptoDelegate* crypto_delegate) {
return scoped_refptr<net::SQLitePersistentCookieStore>(
new net::SQLitePersistentCookieStore(
path,
base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}),
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
restore_old_session_cookies, crypto_delegate));
}
// 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 */, nullptr /* channel_id_service */, 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,
config.crypto_delegate);
std::unique_ptr<net::CookieMonster> cookie_monster(new net::CookieMonster(
persistent_store.get(), nullptr /* channel_id_service */, 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,
net::CookieCryptoDelegate* crypto_delegate)
: path(path),
session_cookie_mode(session_cookie_mode),
cookie_store_type(cookie_store_type),
crypto_delegate(crypto_delegate) {
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);
// On iOS 11, there is no need to use PersistentCookieStore or CookieMonster
// because there is a way to access cookies in WKHTTPCookieStore. This will
// allow URLFetcher and any other users of net:CookieStore to in iOS to set
// and get cookies directly in WKHTTPCookieStore.
if (base::FeatureList::IsEnabled(web::features::kWKHTTPSystemCookieStore)) {
return std::make_unique<net::CookieStoreIOS>(std::move(system_cookie_store),
net_log);
}
scoped_refptr<net::SQLitePersistentCookieStore> persistent_store = nullptr;
if (config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES) {
DCHECK(!config.path.empty());
persistent_store = CreatePersistentCookieStore(
config.path, true /* restore_old_session_cookies */,
config.crypto_delegate);
}
return std::make_unique<net::CookieStoreIOSPersistent>(
persistent_store.get(), std::move(system_cookie_store), net_log);
}
bool ShouldClearSessionCookies() {
NSUserDefaults* standardDefaults = [NSUserDefaults standardUserDefaults];
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t lastCookieDeletionDate =
[standardDefaults integerForKey:kLastCookieDeletionDate];
time_t now;
time(&now);
bool clear_cookies = true;
if (lastCookieDeletionDate != 0 &&
sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
clear_cookies = boottime.tv_sec > lastCookieDeletionDate;
}
if (clear_cookies)
[standardDefaults setInteger:now forKey:kLastCookieDeletionDate];
return clear_cookies;
}
// Clears the session cookies for |profile|.
void ClearSessionCookies(ios::ChromeBrowserState* browser_state) {
scoped_refptr<net::URLRequestContextGetter> getter =
browser_state->GetRequestContext();
base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, base::BindOnce(^{
getter->GetURLRequestContext()
->cookie_store()
->DeleteSessionCookiesAsync(base::DoNothing());
}));
}
} // namespace cookie_util