Commit 336a0871 authored by mrefaat's avatar mrefaat Committed by Commit Bot

[Reland] Convert SystemCookieStore to Async.

* Converts SystemCookieStore to Async
* Add Async functions to NSHTTPSystemCookieStore and keep the synchronous
functions.
* Move creation time management to systemCookieStore.
* Update cookie_store_ios_presistent_unittest &
cookie_store_ios_unittests to account for SystemCookieStore changes
* (As CookieStoreIOS is using systemCookieStore internally).

Another CL is in progress to add WKSystemCookieStore & unit_tests for
systemCookieStore (to handle async methods) with template for both
NSHTTP & WK systemCookieStore.

Bug: 759229, 759227, 767948
Change-Id: If5e1fdb8d6424085d5212a3ea867968642db554f
Reviewed-on: https://chromium-review.googlesource.com/700818Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Commit-Queue: Mohammad Refaat <mrefaat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#506549}
parent 39f3a93a
......@@ -57,6 +57,7 @@ source_set("startup") {
"//ios/chrome/browser:browser_internal",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/first_run",
"//ios/chrome/browser/net:net",
"//ios/chrome/browser/ntp_snippets",
"//ios/chrome/browser/web",
"//ios/chrome/browser/web:web_internal",
......
......@@ -4,7 +4,9 @@
#include "ios/chrome/app/startup/client_registration.h"
#include "ios/chrome/browser/net/chrome_cookie_store_ios_client.h"
#import "ios/chrome/browser/web/chrome_web_client.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
#import "ios/web/public/web_client.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -15,6 +17,9 @@
+ (void)registerClients {
web::SetWebClient(new ChromeWebClient());
// Register CookieStoreIOSClient, This is used to provide CookieStoreIOSClient
// users with WEB::IO task runner.
net::SetCookieStoreIOSClient(new ChromeCookieStoreIOSClient());
}
@end
......@@ -7,28 +7,18 @@
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
@protocol BrowsingDataChangeListening;
// Chrome implementation of net::CookieStoreIOSClient. This class lives on the
// IOThread.
class ChromeCookieStoreIOSClient : public net::CookieStoreIOSClient {
public:
// Creates a CookieStoreIOSClient with a BrowsingDataChangeListening.
// |browsing_data_change_listener| cannot be nil.
explicit ChromeCookieStoreIOSClient(
id<BrowsingDataChangeListening> browsing_data_change_listener);
ChromeCookieStoreIOSClient();
// CookieStoreIOSClient implementation.
void DidChangeCookieStorage() const override;
scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override;
private:
base::ThreadChecker thread_checker_;
// The listener that is informed of change in browsing data.
id<BrowsingDataChangeListening> browsing_data_change_listener_; // Weak.
DISALLOW_COPY_AND_ASSIGN(ChromeCookieStoreIOSClient);
};
......
......@@ -4,31 +4,15 @@
#include "ios/chrome/browser/net/chrome_cookie_store_ios_client.h"
#include "base/logging.h"
#include "base/task_scheduler/post_task.h"
#import "ios/chrome/browser/browsing_data/browsing_data_change_listening.h"
#include "ios/web/public/web_thread.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
ChromeCookieStoreIOSClient::ChromeCookieStoreIOSClient(
id<BrowsingDataChangeListening> browsing_data_change_listener)
: browsing_data_change_listener_(browsing_data_change_listener) {
DCHECK(browsing_data_change_listener);
DCHECK_CURRENTLY_ON(web::WebThread::IO);
}
void ChromeCookieStoreIOSClient::DidChangeCookieStorage() const {
DCHECK(thread_checker_.CalledOnValidThread());
[browsing_data_change_listener_ didChangeCookieStorage];
}
ChromeCookieStoreIOSClient::ChromeCookieStoreIOSClient() {}
scoped_refptr<base::SequencedTaskRunner>
ChromeCookieStoreIOSClient::GetTaskRunner() const {
DCHECK(thread_checker_.CalledOnValidThread());
return base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND});
return web::WebThread::GetTaskRunnerForThread(web::WebThread::IO);
}
......@@ -31,8 +31,6 @@
namespace net {
class CookieCreationTimeManager;
// Observer for changes on |NSHTTPCookieStorge sharedHTTPCookieStorage|.
class CookieNotificationObserver {
public:
......@@ -158,8 +156,6 @@ class CookieStoreIOS : public net::CookieStore,
// deleted.
typedef base::Callback<bool(NSHTTPCookie*, base::Time)> CookieFilterFunction;
// Clears the system cookie store.
void ClearSystemStore();
// Returns true if the system cookie store policy is
// |NSHTTPCookieAcceptPolicyAlways|.
bool SystemCookiesAllowed();
......@@ -169,12 +165,15 @@ class CookieStoreIOS : public net::CookieStore,
// Inherited CookieNotificationObserver methods.
void OnSystemCookiesChanged() override;
void DeleteCookiesWithFilter(const CookieFilterFunction& filter,
DeleteCallback callback);
void DeleteCookiesWithFilterAsync(CookieFilterFunction filter,
DeleteCallback callback);
// Flush to CookieMonster from |cookies|, and run |callback|.
void FlushStoreFromCookies(base::OnceClosure callback,
NSArray<NSHTTPCookie*>* cookies);
std::unique_ptr<net::CookieMonster> cookie_monster_;
std::unique_ptr<SystemCookieStore> system_store_;
std::unique_ptr<CookieCreationTimeManager> creation_time_manager_;
bool metrics_enabled_;
base::CancelableClosure flush_closure_;
......@@ -189,26 +188,22 @@ class CookieStoreIOS : public net::CookieStore,
// the CookieStoreIOS is synchronized and the CookieStore when the
// CookieStoreIOS is not synchronized.
// Fetches any cookies named |name| that would be sent with a request for
// |url| from the system cookie store and pushes them onto the back of the
// vector pointed to by |cookies|. Returns true if any cookies were pushed
// onto the vector, and false otherwise.
bool GetSystemCookies(const GURL& url,
const std::string& name,
std::vector<net::CanonicalCookie>* cookies);
// Updates the cookie cache with cookies named |cookie_name| from the current
// set of |nscookies| that would be sent with a request for |url|.
// |run_callbacks| Run all callbacks registered for cookie named |name| if
// CookieCache was changed.
void UpdateCacheForCookies(const GURL& gurl,
const std::string& cookie_name,
bool run_callbacks,
NSArray<NSHTTPCookie*>* nscookies);
// Updates the cookie cache with the current set of system cookies named
// |name| that would be sent with a request for |url|. Returns whether the
// cache changed.
// |out_removed_cookies|, if not null, will be populated with the cookies that
// were removed.
// |out_changed_cookies|, if not null, will be populated with the cookies that
// were added.
bool UpdateCacheForCookieFromSystem(
const GURL& gurl,
const std::string& name,
std::vector<net::CanonicalCookie>* out_removed_cookies,
std::vector<net::CanonicalCookie>* out_added_cookies);
// |cookie_name| that would be sent with a request for |url|.
// |run_callbacks| Run all callbacks registered for cookie named |name| if
// CookieCache was changed.
void UpdateCacheForCookieFromSystem(const GURL& gurl,
const std::string& cookie_name,
bool run_callbacks);
// Runs all callbacks registered for cookies named |name| that would be sent
// with a request for |url|.
......@@ -228,22 +223,6 @@ class CookieStoreIOS : public net::CookieStore,
// asynchronously invoking callbacks if necessary.
void UpdateCachesFromCookieMonster();
// Called after cookies are cleared from NSHTTPCookieStorage so that cookies
// can be cleared from .binarycookies file. |callback| is called after all the
// cookies are deleted (with the total number of cookies deleted).
// |num_deleted| contains the number of cookies deleted from
// NSHTTPCookieStorage.
void DidClearNSHTTPCookieStorageCookies(DeleteCallback callback,
int num_deleted);
// Called after cookies are cleared from .binarycookies files. |callback| is
// called after all the cookies are deleted with the total number of cookies
// deleted.
// |num_deleted_from_nshttp_cookie_storage| contains the number of cookies
// deleted from NSHTTPCookieStorage.
void DidClearBinaryCookiesFileCookies(
DeleteCallback callback,
int num_deleted_from_nshttp_cookie_storage);
// Callback-wrapping:
// When this CookieStoreIOS object is synchronized with the system store,
// OnSystemCookiesChanged is responsible for updating the cookie cache (and
......@@ -271,6 +250,10 @@ class CookieStoreIOS : public net::CookieStore,
// creation date.
net::CookieList CanonicalCookieListFromSystemCookies(NSArray* cookies);
// Runs |callback| on CanonicalCookie List converted from cookies.
void RunGetCookieListCallbackOnSystemCookies(GetCookieListCallback callback,
NSArray<NSHTTPCookie*>* cookies);
// Cached values of system cookies. Only cookies which have an observer added
// with AddCallbackForCookie are kept in this cache.
std::unique_ptr<CookieCache> cookie_cache_;
......
......@@ -13,6 +13,7 @@
#include "base/ios/ios_util.h"
#include "base/location.h"
#include "base/logging.h"
#import "base/mac/bind_objc_block.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
......@@ -26,7 +27,6 @@
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#import "ios/net/cookies/cookie_creation_time_manager.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
#import "ios/net/cookies/ns_http_system_cookie_store.h"
#import "ios/net/cookies/system_cookie_util.h"
......@@ -118,30 +118,6 @@ NotificationTrampoline* NotificationTrampoline::g_notification_trampoline =
#pragma mark Utility functions
// Returns the path to Cookie.binarycookies file on the file system where
// WKWebView flushes its cookies.
base::FilePath GetBinaryCookiesFilePath() {
base::FilePath path = base::mac::GetUserLibraryPath();
// The relative path of the file (from the user library folder) where
// WKWebView stores its cookies.
const std::string kCookiesFilePath = "Cookies/Cookies.binarycookies";
return path.Append(kCookiesFilePath);
}
// Clears all cookies from the .binarycookies file.
// Must be called from a thread where IO operations are allowed.
// Preconditions: There must be no active WKWebViews present in the app.
// Note that the .binarycookies file is present only on iOS8+.
void ClearAllCookiesFromBinaryCookiesFile() {
base::FilePath path = GetBinaryCookiesFilePath();
if (base::PathExists(path)) {
bool success = base::DeleteFile(path, false);
if (!success) {
DLOG(WARNING) << "Failed to remove binarycookies file.";
}
}
}
// Builds a NSHTTPCookie from a header cookie line ("Set-Cookie: xxx") and a
// URL.
NSHTTPCookie* GetNSHTTPCookieFromCookieLine(const std::string& cookie_line,
......@@ -190,6 +166,28 @@ std::string BuildCookieLineWithOptions(NSArray* cookies,
return base::SysNSStringToUTF8([header valueForKey:@"Cookie"]);
}
// Returns an empty closure if |callback| is null callback or binds the
// callback to |success|.
base::OnceClosure BindSetCookiesCallback(
CookieStoreIOS::SetCookiesCallback* callback,
bool success) {
base::OnceClosure set_callback;
if (!callback->is_null()) {
set_callback = base::BindOnce(std::move(*callback), success);
}
return set_callback;
}
// Runs |callback| on CookieLine generated from |options| and |cookies|.
void RunGetCookiesCallbackOnSystemCookies(
const net::CookieOptions& options,
CookieStoreIOS::GetCookiesCallback callback,
NSArray<NSHTTPCookie*>* cookies) {
if (!callback.is_null()) {
std::move(callback).Run(BuildCookieLineWithOptions(cookies, options));
}
}
// Tests whether the |cookie| is a session cookie.
bool IsCookieSessionCookie(NSHTTPCookie* cookie, base::Time time) {
return [cookie isSessionOnly];
......@@ -315,14 +313,13 @@ void CookieStoreIOS::SetCookieWithOptionsAsync(
(!has_explicit_domain || has_valid_domain);
if (success) {
system_store_->SetCookie(cookie);
creation_time_manager_->SetCreationTime(
cookie,
creation_time_manager_->MakeUniqueCreationTime(base::Time::Now()));
system_store_->SetCookieAsync(cookie,
BindSetCookiesCallback(&callback, true));
return;
}
if (!callback.is_null())
std::move(callback).Run(success);
std::move(callback).Run(false);
}
void CookieStoreIOS::SetCookieWithDetailsAsync(const GURL& url,
......@@ -343,8 +340,6 @@ void CookieStoreIOS::SetCookieWithDetailsAsync(const GURL& url,
// should be written there instead.
DCHECK(SystemCookiesAllowed());
bool success = false;
if (creation_time.is_null())
creation_time = base::Time::Now();
......@@ -388,16 +383,14 @@ void CookieStoreIOS::SetCookieWithDetailsAsync(const GURL& url,
NSHTTPCookie* cookie = SystemCookieFromCanonicalCookie(*canonical_cookie);
if (cookie != nil) {
system_store_->SetCookie(cookie);
creation_time_manager_->SetCreationTime(
cookie, creation_time_manager_->MakeUniqueCreationTime(
canonical_cookie->CreationDate()));
success = true;
system_store_->SetCookieAsync(cookie, &canonical_cookie->CreationDate(),
BindSetCookiesCallback(&callback, true));
return;
}
}
if (!callback.is_null())
std::move(callback).Run(success);
std::move(callback).Run(false);
}
void CookieStoreIOS::SetCanonicalCookieAsync(
......@@ -419,14 +412,8 @@ void CookieStoreIOS::SetCanonicalCookieAsync(
NSHTTPCookie* ns_cookie = SystemCookieFromCanonicalCookie(*cookie.get());
if (ns_cookie != nil) {
system_store_->SetCookie(ns_cookie);
creation_time_manager_->SetCreationTime(
ns_cookie,
creation_time_manager_->MakeUniqueCreationTime(
cookie->CreationDate().is_null() ? base::Time::Now()
: cookie->CreationDate()));
if (!callback.is_null())
std::move(callback).Run(true);
system_store_->SetCookieAsync(ns_cookie, &cookie->CreationDate(),
BindSetCookiesCallback(&callback, true));
return;
}
......@@ -447,12 +434,11 @@ void CookieStoreIOS::GetCookiesWithOptionsAsync(
// engine.
DCHECK(!options.exclude_httponly());
// TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
// options in here as well. https://crbug.com/459154
NSArray* cookies =
system_store_->GetCookiesForURL(url, creation_time_manager_.get());
if (!callback.is_null())
std::move(callback).Run(BuildCookieLineWithOptions(cookies, options));
// TODO(crbug.com/459154): If/when iOS supports Same-Site cookies, we'll need
// to pass options in here as well.
system_store_->GetCookiesForURLAsync(
url, base::BindOnce(&RunGetCookiesCallbackOnSystemCookies, options,
base::Passed(&callback)));
}
void CookieStoreIOS::GetCookieListWithOptionsAsync(
......@@ -470,11 +456,10 @@ void CookieStoreIOS::GetCookieListWithOptionsAsync(
// TODO(mkwst): If/when iOS supports Same-Site cookies, we'll need to pass
// options in here as well. https://crbug.com/459154
NSArray* cookies =
system_store_->GetCookiesForURL(url, creation_time_manager_.get());
net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(cookies);
if (!callback.is_null())
std::move(callback).Run(cookie_list);
system_store_->GetCookiesForURLAsync(
url,
base::BindOnce(&CookieStoreIOS::RunGetCookieListCallbackOnSystemCookies,
weak_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void CookieStoreIOS::GetAllCookiesAsync(GetCookieListCallback callback) {
......@@ -486,30 +471,33 @@ void CookieStoreIOS::GetAllCookiesAsync(GetCookieListCallback callback) {
cookie_monster_->GetAllCookiesAsync(std::move(callback));
return;
}
NSArray* cookies = system_store_->GetAllCookies(creation_time_manager_.get());
net::CookieList cookie_list = CanonicalCookieListFromSystemCookies(cookies);
if (!callback.is_null()) {
std::move(callback).Run(cookie_list);
}
// TODO(crbug.com/459154): If/when iOS supports Same-Site cookies, we'll need
// to pass options in here as well.
system_store_->GetAllCookiesAsync(
base::BindOnce(&CookieStoreIOS::RunGetCookieListCallbackOnSystemCookies,
weak_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void CookieStoreIOS::DeleteCookieAsync(const GURL& url,
const std::string& cookie_name,
base::OnceClosure callback) {
DCHECK(thread_checker_.CalledOnValidThread());
NSArray* cookies =
system_store_->GetCookiesForURL(url, creation_time_manager_.get());
for (NSHTTPCookie* cookie in cookies) {
if ([[cookie name] isEqualToString:base::SysUTF8ToNSString(cookie_name)]) {
system_store_->DeleteCookie(cookie);
creation_time_manager_->DeleteCreationTime(cookie);
}
}
if (!callback.is_null())
std::move(callback).Run();
__block base::OnceClosure shared_callback = std::move(callback);
base::WeakPtr<SystemCookieStore> weak_system_store =
system_store_->GetWeakPtr();
system_store_->GetCookiesForURLAsync(
url, base::BindBlockArc(^(NSArray<NSHTTPCookie*>* cookies) {
for (NSHTTPCookie* cookie in cookies) {
if ([cookie.name
isEqualToString:base::SysUTF8ToNSString(cookie_name)] &&
weak_system_store) {
weak_system_store->DeleteCookieAsync(
cookie, SystemCookieStore::SystemCookieCallback());
}
}
if (!shared_callback.is_null())
std::move(shared_callback).Run();
}));
}
void CookieStoreIOS::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
......@@ -519,7 +507,7 @@ void CookieStoreIOS::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
// This relies on the fact cookies are given unique creation dates.
CookieFilterFunction filter = base::Bind(
IsCookieCreatedBetween, cookie.CreationDate(), cookie.CreationDate());
DeleteCookiesWithFilter(filter, std::move(callback));
DeleteCookiesWithFilterAsync(std::move(filter), std::move(callback));
}
void CookieStoreIOS::DeleteAllCreatedBetweenAsync(
......@@ -533,7 +521,7 @@ void CookieStoreIOS::DeleteAllCreatedBetweenAsync(
CookieFilterFunction filter = base::Bind(
&IsCookieCreatedBetween, delete_begin, delete_end);
DeleteCookiesWithFilter(filter, std::move(callback));
DeleteCookiesWithFilterAsync(std::move(filter), std::move(callback));
}
void CookieStoreIOS::DeleteAllCreatedBetweenWithPredicateAsync(
......@@ -548,7 +536,7 @@ void CookieStoreIOS::DeleteAllCreatedBetweenWithPredicateAsync(
CookieFilterFunction filter = base::Bind(
IsCookieCreatedBetweenWithPredicate, delete_begin, delete_end, predicate);
DeleteCookiesWithFilter(filter, std::move(callback));
DeleteCookiesWithFilterAsync(std::move(filter), std::move(callback));
}
void CookieStoreIOS::DeleteSessionCookiesAsync(DeleteCallback callback) {
......@@ -558,7 +546,7 @@ void CookieStoreIOS::DeleteSessionCookiesAsync(DeleteCallback callback) {
ResetCookieCountMetrics();
CookieFilterFunction filter = base::Bind(&IsCookieSessionCookie);
DeleteCookiesWithFilter(filter, std::move(callback));
DeleteCookiesWithFilterAsync(std::move(filter), std::move(callback));
}
void CookieStoreIOS::FlushStore(base::OnceClosure closure) {
......@@ -567,8 +555,19 @@ void CookieStoreIOS::FlushStore(base::OnceClosure closure) {
if (SystemCookiesAllowed()) {
// If cookies are disabled, the system store is empty, and the cookies are
// stashed on disk. Do not delete the cookies on the disk in this case.
WriteToCookieMonster(system_store_->GetAllCookies());
system_store_->GetAllCookiesAsync(
base ::BindOnce(&CookieStoreIOS::FlushStoreFromCookies,
weak_factory_.GetWeakPtr(), std::move(closure)));
return;
}
cookie_monster_->FlushStore(std::move(closure));
flush_closure_.Cancel();
}
void CookieStoreIOS::FlushStoreFromCookies(base::OnceClosure closure,
NSArray<NSHTTPCookie*>* cookies) {
WriteToCookieMonster(cookies);
cookie_monster_->FlushStore(std::move(closure));
flush_closure_.Cancel();
}
......@@ -581,7 +580,6 @@ CookieStoreIOS::CookieStoreIOS(
std::unique_ptr<SystemCookieStore> system_store)
: cookie_monster_(new net::CookieMonster(persistent_store)),
system_store_(std::move(system_store)),
creation_time_manager_(new CookieCreationTimeManager),
metrics_enabled_(false),
cookie_cache_(new CookieCache()),
weak_factory_(this) {
......@@ -616,12 +614,6 @@ base::OnceClosure CookieStoreIOS::WrapClosure(base::OnceClosure callback) {
#pragma mark -
#pragma mark Private methods
void CookieStoreIOS::ClearSystemStore() {
DCHECK(thread_checker_.CalledOnValidThread());
system_store_->ClearStore();
creation_time_manager_->Clear();
}
bool CookieStoreIOS::SystemCookiesAllowed() {
DCHECK(thread_checker_.CalledOnValidThread());
return system_store_->GetCookieAcceptPolicy() !=
......@@ -637,7 +629,7 @@ void CookieStoreIOS::WriteToCookieMonster(NSArray* system_cookies) {
cookie_list.reserve(cookie_count);
for (NSHTTPCookie* cookie in system_cookies) {
cookie_list.push_back(CanonicalCookieFromSystemCookie(
cookie, creation_time_manager_->GetCreationTime(cookie)));
cookie, system_store_->GetCookieCreationTime(cookie)));
}
cookie_monster_->SetAllCookiesAsync(cookie_list, SetCookiesCallback());
......@@ -646,28 +638,30 @@ void CookieStoreIOS::WriteToCookieMonster(NSArray* system_cookies) {
UMA_HISTOGRAM_COUNTS_10000("CookieIOS.CookieWrittenCount", cookie_count);
}
void CookieStoreIOS::DeleteCookiesWithFilter(const CookieFilterFunction& filter,
DeleteCallback callback) {
void CookieStoreIOS::DeleteCookiesWithFilterAsync(CookieFilterFunction filter,
DeleteCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
NSArray* cookies = system_store_->GetAllCookies();
// Collect the cookies to delete.
base::scoped_nsobject<NSMutableArray> to_delete(
[[NSMutableArray alloc] init]);
for (NSHTTPCookie* cookie in cookies) {
base::Time creation_time = creation_time_manager_->GetCreationTime(cookie);
if (filter.Run(cookie, creation_time))
[to_delete addObject:cookie];
}
// Delete them.
for (NSHTTPCookie* cookie in to_delete.get()) {
system_store_->DeleteCookie(cookie);
creation_time_manager_->DeleteCreationTime(cookie);
}
if (!callback.is_null())
std::move(callback).Run([to_delete count]);
DCHECK(!filter.is_null());
__block DeleteCallback shared_callback = std::move(callback);
__block CookieFilterFunction shared_filter = std::move(filter);
base::WeakPtr<SystemCookieStore> weak_system_store =
system_store_->GetWeakPtr();
system_store_->GetAllCookiesAsync(
base::BindBlockArc(^(NSArray<NSHTTPCookie*>* cookies) {
int to_delete_count = 0;
for (NSHTTPCookie* cookie in cookies) {
if (weak_system_store &&
shared_filter.Run(
cookie, weak_system_store->GetCookieCreationTime(cookie))) {
weak_system_store->DeleteCookieAsync(
cookie, SystemCookieStore::SystemCookieCallback());
to_delete_count++;
}
}
if (!shared_callback.is_null())
std::move(shared_callback).Run(to_delete_count);
}));
}
void CookieStoreIOS::OnSystemCookiesChanged() {
......@@ -675,15 +669,8 @@ void CookieStoreIOS::OnSystemCookiesChanged() {
for (const auto& hook_map_entry : hook_map_) {
std::pair<GURL, std::string> key = hook_map_entry.first;
std::vector<net::CanonicalCookie> removed_cookies;
std::vector<net::CanonicalCookie> added_cookies;
if (UpdateCacheForCookieFromSystem(key.first, key.second, &removed_cookies,
&added_cookies)) {
RunCallbacksForCookies(key.first, key.second, removed_cookies,
net::CookieStore::ChangeCause::UNKNOWN_DELETION);
RunCallbacksForCookies(key.first, key.second, added_cookies,
net::CookieStore::ChangeCause::INSERTED);
}
UpdateCacheForCookieFromSystem(key.first, key.second,
/*run_callbacks=*/true);
}
// Do not schedule a flush if one is already scheduled.
......@@ -705,8 +692,8 @@ CookieStoreIOS::AddCallbackForCookie(const GURL& gurl,
// Prefill cookie cache with all pertinent cookies for |url| if needed.
std::pair<GURL, std::string> key(gurl, name);
if (hook_map_.count(key) == 0) {
UpdateCacheForCookieFromSystem(gurl, name, nullptr, nullptr);
hook_map_[key] = std::make_unique<CookieChangedCallbackList>();
UpdateCacheForCookieFromSystem(gurl, name, /*run_callbacks=*/false);
hook_map_[key] = base::MakeUnique<CookieChangedCallbackList>();
}
DCHECK(hook_map_.find(key) != hook_map_.end());
......@@ -726,16 +713,40 @@ bool CookieStoreIOS::IsEphemeral() {
return cookie_monster_->IsEphemeral();
}
bool CookieStoreIOS::UpdateCacheForCookieFromSystem(
void CookieStoreIOS::UpdateCacheForCookieFromSystem(
const GURL& gurl,
const std::string& name,
std::vector<net::CanonicalCookie>* out_removed_cookies,
std::vector<net::CanonicalCookie>* out_added_cookies) {
const std::string& cookie_name,
bool run_callbacks) {
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<net::CanonicalCookie> system_cookies;
GetSystemCookies(gurl, name, &system_cookies);
return cookie_cache_->Update(gurl, name, system_cookies, out_removed_cookies,
out_added_cookies);
system_store_->GetCookiesForURLAsync(
gurl, base::BindOnce(&CookieStoreIOS::UpdateCacheForCookies,
weak_factory_.GetWeakPtr(), gurl, cookie_name,
run_callbacks));
}
void CookieStoreIOS::UpdateCacheForCookies(const GURL& gurl,
const std::string& cookie_name,
bool run_callbacks,
NSArray<NSHTTPCookie*>* nscookies) {
std::vector<net::CanonicalCookie> cookies;
std::vector<net::CanonicalCookie> out_removed_cookies;
std::vector<net::CanonicalCookie> out_added_cookies;
for (NSHTTPCookie* nscookie in nscookies) {
if (base::SysNSStringToUTF8(nscookie.name) == cookie_name) {
net::CanonicalCookie canonical_cookie = CanonicalCookieFromSystemCookie(
nscookie, system_store_->GetCookieCreationTime(nscookie));
cookies.push_back(canonical_cookie);
}
}
bool changes = cookie_cache_->Update(
gurl, cookie_name, cookies, &out_removed_cookies, &out_added_cookies);
if (run_callbacks && changes) {
RunCallbacksForCookies(gurl, cookie_name, out_removed_cookies,
net::CookieStore::ChangeCause::UNKNOWN_DELETION);
RunCallbacksForCookies(gurl, cookie_name, out_added_cookies,
net::CookieStore::ChangeCause::INSERTED);
}
}
void CookieStoreIOS::RunCallbacksForCookies(
......@@ -755,24 +766,6 @@ void CookieStoreIOS::RunCallbacksForCookies(
}
}
bool CookieStoreIOS::GetSystemCookies(
const GURL& url,
const std::string& name,
std::vector<net::CanonicalCookie>* cookies) {
DCHECK(thread_checker_.CalledOnValidThread());
NSArray* nscookies = system_store_->GetCookiesForURL(url);
bool found_cookies = false;
for (NSHTTPCookie* nscookie in nscookies) {
if (base::SysNSStringToUTF8(nscookie.name) == name) {
net::CanonicalCookie canonical_cookie = CanonicalCookieFromSystemCookie(
nscookie, creation_time_manager_->GetCreationTime(nscookie));
cookies->push_back(canonical_cookie);
found_cookies = true;
}
}
return found_cookies;
}
void CookieStoreIOS::GotCookieListFor(const std::pair<GURL, std::string> key,
const net::CookieList& cookies) {
DCHECK(thread_checker_.CalledOnValidThread());
......@@ -790,35 +783,6 @@ void CookieStoreIOS::GotCookieListFor(const std::pair<GURL, std::string> key,
}
}
void CookieStoreIOS::DidClearNSHTTPCookieStorageCookies(
DeleteCallback delete_callback,
int num_deleted) {
DCHECK(thread_checker_.CalledOnValidThread());
CookieStoreIOSClient* client = net::GetCookieStoreIOSClient();
DCHECK(client);
auto sequenced_task_runner = client->GetTaskRunner();
DCHECK(sequenced_task_runner);
auto callback = base::BindOnce(
&CookieStoreIOS::DidClearBinaryCookiesFileCookies,
weak_factory_.GetWeakPtr(), std::move(delete_callback), num_deleted);
sequenced_task_runner.get()->PostTaskAndReply(
FROM_HERE, base::Bind(&ClearAllCookiesFromBinaryCookiesFile),
std::move(callback));
}
void CookieStoreIOS::DidClearBinaryCookiesFileCookies(
DeleteCallback callback,
int num_deleted_from_nshttp_cookie_storage) {
DCHECK(thread_checker_.CalledOnValidThread());
CookieStoreIOSClient* client = net::GetCookieStoreIOSClient();
DCHECK(client);
client->DidChangeCookieStorage();
if (!callback.is_null())
std::move(callback).Run(num_deleted_from_nshttp_cookie_storage);
}
void CookieStoreIOS::UpdateCachesFromCookieMonster() {
DCHECK(thread_checker_.CalledOnValidThread());
for (const auto& hook_map_entry : hook_map_) {
......@@ -858,10 +822,18 @@ CookieStoreIOS::CanonicalCookieListFromSystemCookies(NSArray* cookies) {
net::CookieList cookie_list;
cookie_list.reserve([cookies count]);
for (NSHTTPCookie* cookie in cookies) {
base::Time created = creation_time_manager_->GetCreationTime(cookie);
base::Time created = system_store_->GetCookieCreationTime(cookie);
cookie_list.push_back(CanonicalCookieFromSystemCookie(cookie, created));
}
return cookie_list;
}
void CookieStoreIOS::RunGetCookieListCallbackOnSystemCookies(
CookieStoreIOS::GetCookieListCallback callback,
NSArray<NSHTTPCookie*>* cookies) {
if (!callback.is_null()) {
std::move(callback).Run(CanonicalCookieListFromSystemCookies(cookies));
}
}
} // namespace net
......@@ -24,13 +24,6 @@ class CookieStoreIOSClient {
CookieStoreIOSClient();
virtual ~CookieStoreIOSClient();
// Gives the embedder a chance to perform tasks before the cookie storage is
// changed.
virtual void WillChangeCookieStorage() const;
// Informs the embedder after the cookie storage has been changed.
virtual void DidChangeCookieStorage() const;
// Returns instance of SequencedTaskRunner used for blocking file I/O.
virtual scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const;
......
......@@ -27,10 +27,6 @@ CookieStoreIOSClient::CookieStoreIOSClient() {}
CookieStoreIOSClient::~CookieStoreIOSClient() {}
void CookieStoreIOSClient::WillChangeCookieStorage() const {}
void CookieStoreIOSClient::DidChangeCookieStorage() const {}
scoped_refptr<base::SequencedTaskRunner>
CookieStoreIOSClient::GetTaskRunner() const {
return scoped_refptr<base::SequencedTaskRunner>();
......
......@@ -56,6 +56,8 @@ class CookieStoreIOSPersistentTest : public testing::Test {
public:
CookieStoreIOSPersistentTest()
: kTestCookieURL("http://foo.google.com/bar"),
scoped_cookie_store_ios_client_(
base::MakeUnique<TestCookieStoreIOSClient>()),
backend_(new net::TestPersistentCookieStore),
store_(
base::MakeUnique<net::CookieStoreIOSPersistent>(backend_.get())) {
......@@ -85,6 +87,7 @@ class CookieStoreIOSPersistentTest : public testing::Test {
protected:
base::MessageLoop loop_;
ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
scoped_refptr<net::TestPersistentCookieStore> backend_;
std::unique_ptr<net::CookieStoreIOS> store_;
std::unique_ptr<net::CookieStore::CookieChangedSubscription>
......
......@@ -9,6 +9,8 @@
#include <vector>
#include "base/callback_forward.h"
#include "base/task_scheduler/post_task.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "url/gurl.h"
......@@ -66,6 +68,26 @@ class GetCookieCallback {
std::string cookie_line_;
};
class TestCookieStoreIOSClient : public CookieStoreIOSClient {
public:
TestCookieStoreIOSClient();
// CookieStoreIOSClient implementation.
scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override;
};
class ScopedTestingCookieStoreIOSClient {
public:
explicit ScopedTestingCookieStoreIOSClient(
std::unique_ptr<CookieStoreIOSClient> cookie_store_client);
~ScopedTestingCookieStoreIOSClient();
CookieStoreIOSClient* Get();
private:
std::unique_ptr<CookieStoreIOSClient> cookie_store_client_;
CookieStoreIOSClient* original_client_;
};
void RecordCookieChanges(std::vector<net::CanonicalCookie>* out_cookies,
std::vector<bool>* out_removes,
const net::CanonicalCookie& cookie,
......
......@@ -8,6 +8,8 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#import "ios/net/cookies/cookie_store_ios.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_options.h"
......@@ -113,6 +115,33 @@ void GetCookieCallback::Run(const std::string& cookie_line) {
cookie_line_ = cookie_line;
}
#pragma mark -
#pragma mark TestCookieStoreIOSClient
TestCookieStoreIOSClient::TestCookieStoreIOSClient() {}
#pragma mark -
#pragma mark TestCookieStoreIOSClient methods
scoped_refptr<base::SequencedTaskRunner>
TestCookieStoreIOSClient::GetTaskRunner() const {
return base::ThreadTaskRunnerHandle::Get();
}
#pragma mark -
#pragma mark ScopedTestingCookieStoreIOSClient
ScopedTestingCookieStoreIOSClient::ScopedTestingCookieStoreIOSClient(
std::unique_ptr<CookieStoreIOSClient> cookie_store_client)
: cookie_store_client_(std::move(cookie_store_client)),
original_client_(GetCookieStoreIOSClient()) {
SetCookieStoreIOSClient(cookie_store_client_.get());
}
ScopedTestingCookieStoreIOSClient::~ScopedTestingCookieStoreIOSClient() {
SetCookieStoreIOSClient(original_client_);
}
//------------------------------------------------------------------------------
void RecordCookieChanges(std::vector<net::CanonicalCookie>* out_cookies,
......
......@@ -9,11 +9,13 @@
#include <memory>
#include "base/bind_helpers.h"
#import "base/mac/bind_objc_block.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
#import "ios/net/cookies/cookie_store_ios_test_util.h"
#import "ios/net/cookies/ns_http_system_cookie_store.h"
#import "net/base/mac/url_conversions.h"
......@@ -26,10 +28,21 @@
namespace net {
class TestingCookieStoreIOS : public CookieStoreIOS {
public:
TestingCookieStoreIOS(std::unique_ptr<SystemCookieStore> system_store)
: CookieStoreIOS(std::move(system_store)),
scoped_cookie_store_ios_client_(
base::MakeUnique<TestCookieStoreIOSClient>()) {}
private:
ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
};
struct CookieStoreIOSTestTraits {
static std::unique_ptr<net::CookieStore> Create() {
ClearCookies();
return base::MakeUnique<CookieStoreIOS>(
return base::MakeUnique<TestingCookieStoreIOS>(
base::MakeUnique<NSHTTPSystemCookieStore>());
}
......@@ -91,6 +104,8 @@ class CookieStoreIOSTest : public testing::Test {
kTestCookieURLFooBaz("http://foo.google.com/baz"),
kTestCookieURLFoo("http://foo.google.com"),
kTestCookieURLBarBar("http://bar.google.com/bar"),
scoped_cookie_store_ios_client_(
base::MakeUnique<TestCookieStoreIOSClient>()),
backend_(new TestPersistentCookieStore) {
ClearCookies();
std::unique_ptr<NSHTTPSystemCookieStore> system_store(
......@@ -122,25 +137,33 @@ class CookieStoreIOSTest : public testing::Test {
void SetSystemCookie(const GURL& url,
const std::string& name,
const std::string& value) {
system_store_->SetCookie([NSHTTPCookie cookieWithProperties:@{
NSHTTPCookiePath : base::SysUTF8ToNSString(url.path()),
NSHTTPCookieName : base::SysUTF8ToNSString(name),
NSHTTPCookieValue : base::SysUTF8ToNSString(value),
NSHTTPCookieDomain : base::SysUTF8ToNSString(url.host()),
}]);
net::CookieStoreIOS::NotifySystemCookiesChanged();
system_store_->SetCookieAsync(
[NSHTTPCookie cookieWithProperties:@{
NSHTTPCookiePath : base::SysUTF8ToNSString(url.path()),
NSHTTPCookieName : base::SysUTF8ToNSString(name),
NSHTTPCookieValue : base::SysUTF8ToNSString(value),
NSHTTPCookieDomain : base::SysUTF8ToNSString(url.host()),
}],
base::BindOnce(&net::CookieStoreIOS::NotifySystemCookiesChanged));
base::RunLoop().RunUntilIdle();
}
void DeleteSystemCookie(const GURL& gurl, const std::string& name) {
NSArray* cookies = system_store_->GetCookiesForURL(gurl);
for (NSHTTPCookie* cookie in cookies) {
if (cookie.name.UTF8String == name) {
system_store_->DeleteCookie(cookie);
break;
}
}
net::CookieStoreIOS::NotifySystemCookiesChanged();
base::WeakPtr<SystemCookieStore> weak_system_store =
system_store_->GetWeakPtr();
system_store_->GetCookiesForURLAsync(
gurl, base::BindBlockArc(^(NSArray<NSHTTPCookie*>* cookies) {
for (NSHTTPCookie* cookie in cookies) {
if ([[cookie name] isEqualToString:base::SysUTF8ToNSString(name)] &&
weak_system_store) {
weak_system_store->DeleteCookieAsync(
cookie,
base::BindOnce(
&net::CookieStoreIOS::NotifySystemCookiesChanged));
break;
}
}
}));
base::RunLoop().RunUntilIdle();
}
......@@ -151,6 +174,7 @@ class CookieStoreIOSTest : public testing::Test {
const GURL kTestCookieURLBarBar;
base::MessageLoop loop_;
ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
scoped_refptr<TestPersistentCookieStore> backend_;
// |system_store_| will point to the NSHTTPSystemCookieStore object owned by
// |store_|. Once the store_ object is deleted the NSHTTPSystemCookieStore
......@@ -210,6 +234,8 @@ TEST_F(CookieStoreIOSTest, SameValueDoesNotCallHook) {
TEST(CookieStoreIOS, GetAllCookiesForURLAsync) {
base::MessageLoop loop;
const GURL kTestCookieURLFooBar("http://foo.google.com/bar");
ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client(
base::MakeUnique<TestCookieStoreIOSClient>());
ClearCookies();
std::unique_ptr<CookieStoreIOS> cookie_store(base::MakeUnique<CookieStoreIOS>(
base::MakeUnique<NSHTTPSystemCookieStore>()));
......@@ -225,6 +251,7 @@ TEST(CookieStoreIOS, GetAllCookiesForURLAsync) {
cookie_store->GetAllCookiesForURLAsync(
kTestCookieURLFooBar,
base::Bind(&GetAllCookiesCallback::Run, base::Unretained(&callback)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback.did_run());
EXPECT_EQ(1u, callback.cookie_list().size());
net::CanonicalCookie cookie = callback.cookie_list()[0];
......
......@@ -18,17 +18,54 @@ class NSHTTPSystemCookieStore : public net::SystemCookieStore {
// By default the underlying cookiestore is
// |NSHTTPCookieStorage sharedHTTPCookieStorage|
NSHTTPSystemCookieStore();
explicit NSHTTPSystemCookieStore(NSHTTPCookieStorage* cookie_store);
~NSHTTPSystemCookieStore() override;
NSArray* GetCookiesForURL(const GURL& url,
CookieCreationTimeManager* manager) override;
NSArray* GetAllCookies(CookieCreationTimeManager* manager) override;
void DeleteCookie(NSHTTPCookie* cookie) override;
void SetCookie(NSHTTPCookie* cookie) override;
void ClearStore() override;
// Gets cookies for URL and calls |callback| async on these cookies.
void GetCookiesForURLAsync(const GURL& url,
SystemCookieCallbackForCookies callback) override;
// Gets all cookies and calls |callback| async on these cookies.
void GetAllCookiesAsync(SystemCookieCallbackForCookies callback) override;
// Deletes specific cookie and calls |callback| async after that.
void DeleteCookieAsync(NSHTTPCookie* cookie,
SystemCookieCallback callback) override;
// Sets cookie, and calls |callback| async after that.
void SetCookieAsync(NSHTTPCookie* cookie,
const base::Time* optional_creation_time,
SystemCookieCallback callback) override;
// Clears all cookies from the store and call |callback| after all cookies are
// deleted.
void ClearStoreAsync(SystemCookieCallback callback) override;
NSHTTPCookieAcceptPolicy GetCookieAcceptPolicy() override;
private:
// Returns all cookies for a specific |url| from the internal cookie store.
// Cookies are sorted, as per RFC6265.
NSArray* GetCookiesForURL(const GURL& url);
// Returns all cookies from the internal http cookie store.
// Cookies are sorted, as per RFC6265.
NSArray* GetAllCookies();
// Deletes a specific cookie from the internal http cookie store.
void DeleteCookie(NSHTTPCookie* cookie);
// Sets a specific cookie to the internal http cookie store.
// if the |optional_creation_time| is nullptr, uses Time::Now() as the
// creation time.
void SetCookie(NSHTTPCookie* cookie,
const base::Time* optional_creation_time);
// Clears all cookies from the internal cookie store.
void ClearStore();
NSHTTPCookieStorage* cookie_store_;
DISALLOW_COPY_AND_ASSIGN(NSHTTPSystemCookieStore);
......
......@@ -4,7 +4,10 @@
#import "ios/net/cookies/ns_http_system_cookie_store.h"
#include "base/bind.h"
#include "base/time/time.h"
#import "ios/net/cookies/cookie_creation_time_manager.h"
#import "ios/net/cookies/cookie_store_ios_client.h"
#import "net/base/mac/url_conversions.h"
#include "url/gurl.h"
......@@ -14,6 +17,15 @@
namespace net {
// private
void RunCookieCallback(base::OnceClosure callback) {
if (callback.is_null())
return;
CookieStoreIOSClient* client = net::GetCookieStoreIOSClient();
auto sequenced_task_runner = client->GetTaskRunner();
sequenced_task_runner->PostTask(FROM_HERE, std::move(callback));
}
NSHTTPSystemCookieStore::NSHTTPSystemCookieStore()
: cookie_store_([NSHTTPCookieStorage sharedHTTPCookieStorage]) {}
......@@ -26,33 +38,71 @@ NSHTTPSystemCookieStore::~NSHTTPSystemCookieStore() = default;
#pragma mark -
#pragma mark SystemCookieStore methods
NSArray* NSHTTPSystemCookieStore::GetCookiesForURL(
void NSHTTPSystemCookieStore::GetCookiesForURLAsync(
const GURL& url,
CookieCreationTimeManager* manager) {
SystemCookieCallbackForCookies callback) {
NSArray* cookies = GetCookiesForURL(url);
RunCookieCallback(base::BindOnce(std::move(callback), cookies));
}
void NSHTTPSystemCookieStore::GetAllCookiesAsync(
SystemCookieCallbackForCookies callback) {
NSArray* cookies = GetAllCookies();
RunCookieCallback(base::BindOnce(std::move(callback), cookies));
}
void NSHTTPSystemCookieStore::DeleteCookieAsync(NSHTTPCookie* cookie,
SystemCookieCallback callback) {
DeleteCookie(cookie);
RunCookieCallback(std::move(callback));
}
void NSHTTPSystemCookieStore::SetCookieAsync(
NSHTTPCookie* cookie,
const base::Time* optional_creation_time,
SystemCookieCallback callback) {
SetCookie(cookie, optional_creation_time);
RunCookieCallback(std::move(callback));
}
void NSHTTPSystemCookieStore::ClearStoreAsync(SystemCookieCallback callback) {
ClearStore();
RunCookieCallback(std::move(callback));
}
NSHTTPCookieAcceptPolicy NSHTTPSystemCookieStore::GetCookieAcceptPolicy() {
return [cookie_store_ cookieAcceptPolicy];
}
#pragma mark private methods
NSArray* NSHTTPSystemCookieStore::GetCookiesForURL(const GURL& url) {
NSArray* cookies = [cookie_store_ cookiesForURL:NSURLWithGURL(url)];
if (!manager)
return cookies;
// Sort cookies by decreasing path length, then creation time, as per
// RFC6265.
return [cookies sortedArrayUsingFunction:CompareCookies context:manager];
return [cookies sortedArrayUsingFunction:CompareCookies
context:creation_time_manager_.get()];
}
NSArray* NSHTTPSystemCookieStore::GetAllCookies(
CookieCreationTimeManager* manager) {
NSArray* NSHTTPSystemCookieStore::GetAllCookies() {
NSArray* cookies = cookie_store_.cookies;
if (!manager)
return cookies;
// Sort cookies by decreasing path length, then creation time, as per
// RFC6265.
return [cookies sortedArrayUsingFunction:CompareCookies context:manager];
return [cookies sortedArrayUsingFunction:CompareCookies
context:creation_time_manager_.get()];
}
void NSHTTPSystemCookieStore::DeleteCookie(NSHTTPCookie* cookie) {
[cookie_store_ deleteCookie:cookie];
creation_time_manager_->DeleteCreationTime(cookie);
}
void NSHTTPSystemCookieStore::SetCookie(NSHTTPCookie* cookie) {
void NSHTTPSystemCookieStore::SetCookie(
NSHTTPCookie* cookie,
const base::Time* optional_creation_time) {
[cookie_store_ setCookie:cookie];
base::Time cookie_time = base::Time::Now();
if (optional_creation_time && !optional_creation_time->is_null())
cookie_time = *optional_creation_time;
creation_time_manager_->SetCreationTime(
cookie, creation_time_manager_->MakeUniqueCreationTime(cookie_time));
}
void NSHTTPSystemCookieStore::ClearStore() {
......@@ -60,10 +110,6 @@ void NSHTTPSystemCookieStore::ClearStore() {
for (NSHTTPCookie* cookie in copy)
[cookie_store_ deleteCookie:cookie];
DCHECK_EQ(0u, cookie_store_.cookies.count);
creation_time_manager_->Clear();
}
NSHTTPCookieAcceptPolicy NSHTTPSystemCookieStore::GetCookieAcceptPolicy() {
return [cookie_store_ cookieAcceptPolicy];
}
} // namespace net
......@@ -8,7 +8,13 @@
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#import "ios/net/cookies/cookie_store_ios_test_util.h"
#import "net/base/mac/url_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
......@@ -20,12 +26,45 @@
namespace net {
namespace {
// Helper callbacks to be passed to SetCookieAsync/GetCookiesAsync.
class SystemCookiesCallback {
public:
SystemCookiesCallback()
: did_run_with_cookies_(false), did_run_with_no_cookies_(false) {}
// Returns if the callback has been run.
bool did_run_with_cookies() { return did_run_with_cookies_; }
bool did_run_with_no_cookies() { return did_run_with_no_cookies_; }
// Returns the paremeter of the callback.
NSArray<NSHTTPCookie*>* cookies() { return cookies_; }
void RunWithCookies(NSArray<NSHTTPCookie*>* cookies) {
ASSERT_FALSE(did_run_with_cookies_);
did_run_with_cookies_ = true;
cookies_ = cookies;
}
void RunWithNoCookies() {
ASSERT_FALSE(did_run_with_no_cookies_);
did_run_with_no_cookies_ = true;
}
private:
bool did_run_with_cookies_;
bool did_run_with_no_cookies_;
NSArray<NSHTTPCookie*>* cookies_;
};
} // namespace
// Test fixture to exercise net::NSHTTPSystemCookieStore created with
// |[NSHTTPCookieStorage sharedHTTPCookieStorage]|.
class NSHTTPSystemCookieStoreTest : public PlatformTest {
public:
NSHTTPSystemCookieStoreTest()
: shared_store_([NSHTTPCookieStorage sharedHTTPCookieStorage]),
: scoped_cookie_store_ios_client_(
base::MakeUnique<TestCookieStoreIOSClient>()),
shared_store_([NSHTTPCookieStorage sharedHTTPCookieStorage]),
store_(base::MakeUnique<net::NSHTTPSystemCookieStore>(shared_store_)),
test_cookie_url1_([NSURL URLWithString:@"http://foo.google.com/bar"]),
test_cookie_url2_([NSURL URLWithString:@"http://bar.xyz.abc"]),
......@@ -46,7 +85,22 @@ class NSHTTPSystemCookieStoreTest : public PlatformTest {
forURL:url] objectAtIndex:0];
}
bool IsCookieSet(NSHTTPCookie* system_cookie, NSURL* url) {
// Verify that cookie is set in system storage.
NSHTTPCookie* result_cookie = nil;
for (NSHTTPCookie* cookie in [shared_store_ cookiesForURL:url]) {
if ([cookie.name isEqualToString:system_cookie.name]) {
result_cookie = cookie;
break;
}
}
return [result_cookie.value isEqualToString:system_cookie.value];
}
protected:
base::MessageLoop loop;
ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
NSHTTPCookieStorage* shared_store_;
std::unique_ptr<net::NSHTTPSystemCookieStore> store_;
NSURL* test_cookie_url1_;
......@@ -54,105 +108,126 @@ class NSHTTPSystemCookieStoreTest : public PlatformTest {
NSURL* test_cookie_url3_;
};
TEST_F(NSHTTPSystemCookieStoreTest, SetCookie) {
NSHTTPCookie* system_cookie = CreateCookie(@"a=b", test_cookie_url1_);
// Verify that cookie is not set in system storage.
for (NSHTTPCookie* cookie in
[shared_store_ cookiesForURL:test_cookie_url1_]) {
EXPECT_FALSE([cookie.name isEqualToString:system_cookie.name]);
}
store_->SetCookie(system_cookie);
// Verify that cookie is set in system storage.
NSHTTPCookie* result_cookie = nil;
for (NSHTTPCookie* cookie in
[shared_store_ cookiesForURL:test_cookie_url1_]) {
if ([cookie.name isEqualToString:system_cookie.name]) {
result_cookie = cookie;
break;
}
}
EXPECT_TRUE([result_cookie.value isEqualToString:system_cookie.value]);
}
TEST_F(NSHTTPSystemCookieStoreTest, ClearCookies) {
[shared_store_ setCookie:CreateCookie(@"a=b", test_cookie_url1_)];
[shared_store_ setCookie:CreateCookie(@"x=d", test_cookie_url2_)];
EXPECT_EQ(2u, shared_store_.cookies.count);
store_->ClearStore();
EXPECT_EQ(0u, shared_store_.cookies.count);
TEST_F(NSHTTPSystemCookieStoreTest, GetCookieAcceptPolicy) {
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
shared_store_.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
shared_store_.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
}
TEST_F(NSHTTPSystemCookieStoreTest, GetCookies) {
TEST_F(NSHTTPSystemCookieStoreTest, GetCookiesAsync) {
NSMutableDictionary* input_cookies = [[NSMutableDictionary alloc] init];
NSHTTPCookie* system_cookie = CreateCookie(@"a=b", test_cookie_url1_);
[input_cookies setValue:system_cookie forKey:@"a"];
[shared_store_ setCookie:system_cookie];
store_->SetCookieAsync(system_cookie, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
system_cookie = CreateCookie(@"x=d", test_cookie_url2_);
[input_cookies setValue:system_cookie forKey:@"x"];
[shared_store_ setCookie:system_cookie];
store_->SetCookieAsync(system_cookie, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
system_cookie = CreateCookie(@"l=m", test_cookie_url3_);
[input_cookies setValue:system_cookie forKey:@"l"];
[shared_store_ setCookie:system_cookie];
store_->SetCookieAsync(system_cookie, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, shared_store_.cookies.count);
// Test GetCookieForURLAsync.
NSHTTPCookie* input_cookie = [input_cookies valueForKey:@"a"];
SystemCookiesCallback callback_for_url;
store_->GetCookiesForURLAsync(
GURLWithNSURL(test_cookie_url1_),
base::BindOnce(&SystemCookiesCallback::RunWithCookies,
base::Unretained(&callback_for_url)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_for_url.did_run_with_cookies());
EXPECT_EQ(1u, callback_for_url.cookies().count);
NSHTTPCookie* result_cookie = callback_for_url.cookies()[0];
EXPECT_TRUE([input_cookie.name isEqualToString:result_cookie.name]);
EXPECT_TRUE([input_cookie.value isEqualToString:result_cookie.value]);
// Test GetAllCookies
NSArray* cookies = store_->GetAllCookies(/*manager=*/nullptr);
EXPECT_EQ(3u, cookies.count);
for (NSHTTPCookie* cookie in cookies) {
SystemCookiesCallback callback_all_cookies;
store_->GetAllCookiesAsync(
base::BindOnce(&SystemCookiesCallback::RunWithCookies,
base::Unretained(&callback_all_cookies)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_all_cookies.did_run_with_cookies());
NSArray<NSHTTPCookie*>* result_cookies = callback_all_cookies.cookies();
EXPECT_EQ(3u, result_cookies.count);
for (NSHTTPCookie* cookie in result_cookies) {
NSHTTPCookie* existing_cookie = [input_cookies valueForKey:cookie.name];
EXPECT_TRUE(existing_cookie);
EXPECT_TRUE([existing_cookie.name isEqualToString:cookie.name]);
EXPECT_TRUE([existing_cookie.value isEqualToString:cookie.value]);
EXPECT_TRUE([existing_cookie.domain isEqualToString:cookie.domain]);
}
}
// Test GetCookiesForURL
NSHTTPCookie* input_cookie = [input_cookies valueForKey:@"a"];
NSArray* cookies_for_url = store_->GetCookiesForURL(
GURLWithNSURL(test_cookie_url1_), /*manager=*/nullptr);
EXPECT_EQ(1u, cookies_for_url.count);
NSHTTPCookie* output_cookie = [cookies_for_url objectAtIndex:0];
EXPECT_TRUE([input_cookie.name isEqualToString:output_cookie.name]);
EXPECT_TRUE([input_cookie.value isEqualToString:output_cookie.value]);
EXPECT_TRUE([input_cookie.domain isEqualToString:output_cookie.domain]);
TEST_F(NSHTTPSystemCookieStoreTest, SetCookieAsync) {
NSHTTPCookie* system_cookie = CreateCookie(@"a=b", test_cookie_url1_);
SystemCookiesCallback callback;
store_->SetCookieAsync(
system_cookie, /*optional_creation_time=*/nullptr,
base::BindOnce(&SystemCookiesCallback::RunWithNoCookies,
base::Unretained(&callback)));
base::RunLoop().RunUntilIdle();
// verify callback.
EXPECT_TRUE(callback.did_run_with_no_cookies());
EXPECT_TRUE(IsCookieSet(system_cookie, test_cookie_url1_));
}
TEST_F(NSHTTPSystemCookieStoreTest, DeleteCookies) {
TEST_F(NSHTTPSystemCookieStoreTest, DeleteCookiesAsync) {
NSHTTPCookie* system_cookie1 = CreateCookie(@"a=b", test_cookie_url1_);
[shared_store_ setCookie:system_cookie1];
store_->SetCookieAsync(system_cookie1, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
NSHTTPCookie* system_cookie2 = CreateCookie(@"x=d", test_cookie_url2_);
store_->SetCookie(system_cookie2);
store_->SetCookieAsync(system_cookie2, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
NSHTTPCookie* system_cookie3 = CreateCookie(@"l=m", test_cookie_url3_);
[shared_store_ setCookie:system_cookie3];
store_->SetCookieAsync(system_cookie3, /*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, shared_store_.cookies.count);
store_->DeleteCookie(system_cookie2);
SystemCookiesCallback callback;
EXPECT_EQ(1u, [shared_store_ cookiesForURL:test_cookie_url2_].count);
store_->DeleteCookieAsync(
system_cookie2, base::BindOnce(&SystemCookiesCallback::RunWithNoCookies,
base::Unretained(&callback)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback.did_run_with_no_cookies());
EXPECT_EQ(0u, [shared_store_ cookiesForURL:test_cookie_url2_].count);
EXPECT_EQ(2u, shared_store_.cookies.count);
store_->DeleteCookie(system_cookie1);
store_->DeleteCookieAsync(system_cookie1,
SystemCookieStore::SystemCookieCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, [shared_store_ cookiesForURL:test_cookie_url1_].count);
EXPECT_EQ(1u, shared_store_.cookies.count);
store_->DeleteCookie(system_cookie3);
store_->DeleteCookieAsync(system_cookie3,
SystemCookieStore::SystemCookieCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, shared_store_.cookies.count);
}
TEST_F(NSHTTPSystemCookieStoreTest, GetCookieAcceptPolicy) {
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
shared_store_.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
shared_store_.cookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
EXPECT_EQ(shared_store_.cookieAcceptPolicy, store_->GetCookieAcceptPolicy());
TEST_F(NSHTTPSystemCookieStoreTest, ClearCookiesAsync) {
store_->SetCookieAsync(CreateCookie(@"a=b", test_cookie_url1_),
/*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
store_->SetCookieAsync(CreateCookie(@"x=d", test_cookie_url2_),
/*optional_creation_time=*/nullptr,
SystemCookieStore::SystemCookieCallback());
SystemCookiesCallback callback;
EXPECT_EQ(2u, shared_store_.cookies.count);
store_->ClearStoreAsync(base::BindOnce(
&SystemCookiesCallback::RunWithNoCookies, base::Unretained(&callback)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback.did_run_with_no_cookies());
EXPECT_EQ(0u, shared_store_.cookies.count);
}
} // namespace net
......@@ -7,7 +7,10 @@
#import <Foundation/Foundation.h>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
class GURL;
......@@ -21,39 +24,67 @@ class CookieCreationTimeManager;
// it directly without caring about the type of the underlying cookie store.
class SystemCookieStore {
public:
virtual ~SystemCookieStore();
// Returns cookies for specific URL without sorting.
NSArray* GetCookiesForURL(const GURL& url);
// Returns all cookies for a specific |url| from the internal cookie store.
// If |manager| is provided, use it to sort cookies, as per RFC6265.
virtual NSArray* GetCookiesForURL(const GURL& url,
CookieCreationTimeManager* manager) = 0;
// Returns all cookies from the internal http cookie store without sorting.
NSArray* GetAllCookies();
// Returns all cookies from the internal http cookie store.
// If |manager| is provided, use it to sort cookies, as per RFC6265.
virtual NSArray* GetAllCookies(CookieCreationTimeManager* manager) = 0;
// Delete a specific cookie from the internal http cookie store.
virtual void DeleteCookie(NSHTTPCookie* cookie) = 0;
// Callback definitions.
typedef base::OnceClosure SystemCookieCallback;
typedef base::OnceCallback<void(NSArray<NSHTTPCookie*>*)>
SystemCookieCallbackForCookies;
// Set a specific cookie to the internal http cookie store.
virtual void SetCookie(NSHTTPCookie* cookie) = 0;
SystemCookieStore();
virtual ~SystemCookieStore();
// Delete all cookies from the internal http cookie store.
virtual void ClearStore() = 0;
// Calls |callback| on all cookies for a specific |url| in the internal
// cookie store.
// If CookieCreationTimeManager was provided in the constructor, sort cookies
// as per RFC6265 before calling the |callback|.
virtual void GetCookiesForURLAsync(
const GURL& url,
SystemCookieCallbackForCookies callback) = 0;
// Calls |callback| on all cookies in the internal cookie store.
// If CookieCreationTimeManager was provided in the constructor, sort cookies
// as per RFC6265 before calling the |callback|.
virtual void GetAllCookiesAsync(SystemCookieCallbackForCookies callback) = 0;
// Deletes a specific cookie from the internal cookie store, and call
// |callback| after it's deleted.
virtual void DeleteCookieAsync(NSHTTPCookie* cookie,
SystemCookieCallback callback) = 0;
// Sets a specific cookie to the internal cookie store, sets the cookie
// creation time |optional_creation_time| or to the current time if
// |optional_creation_time| is nil, then calls |callback| after it's set.
virtual void SetCookieAsync(NSHTTPCookie* cookie,
const base::Time* optional_creation_time,
SystemCookieCallback callback) = 0;
// Same as SetCookieAsync but uses actual time of setting the cookie.
void SetCookieAsync(NSHTTPCookie* cookie, SystemCookieCallback callback);
// Deletes all cookies from the internal http cookie store, and calls
// |callback| all cookies are deleted.
virtual void ClearStoreAsync(SystemCookieCallback callback) = 0;
// Returns the Cookie Accept policy for the internal cookie store.
virtual NSHTTPCookieAcceptPolicy GetCookieAcceptPolicy() = 0;
// Returns the creation time of a specific cookie
base::Time GetCookieCreationTime(NSHTTPCookie* cookie);
// Return WeakPtr of this object.
base::WeakPtr<SystemCookieStore> GetWeakPtr();
protected:
// Compares cookies based on the path lengths and the creation times, as per
// RFC6265.
static NSInteger CompareCookies(id a, id b, void* context);
// Internal cookie stores doesn't store creation time. This object is used
// to keep track of the creation time of cookies, this is required for
// conversion between SystemCookie and Chromium CookieMonster.
std::unique_ptr<CookieCreationTimeManager> creation_time_manager_;
// Weak Ptr factory.
base::WeakPtrFactory<SystemCookieStore> weak_factory_;
};
} // namespace net
......
......@@ -4,7 +4,7 @@
#import "ios/net/cookies/system_cookie_store.h"
#include "base/time/time.h"
#include "base/memory/ptr_util.h"
#import "ios/net/cookies/cookie_creation_time_manager.h"
#include "ios/net/ios_net_features.h"
......@@ -16,12 +16,22 @@ namespace net {
SystemCookieStore::~SystemCookieStore() = default;
NSArray* SystemCookieStore::GetCookiesForURL(const GURL& url) {
return GetCookiesForURL(url, /* manager = */ nullptr);
SystemCookieStore::SystemCookieStore()
: creation_time_manager_(base::MakeUnique<CookieCreationTimeManager>()),
weak_factory_(this) {}
void SystemCookieStore::SetCookieAsync(NSHTTPCookie* cookie,
SystemCookieCallback callback) {
SetCookieAsync(cookie, /*optional_creation_time=*/nullptr,
std::move(callback));
}
base::Time SystemCookieStore::GetCookieCreationTime(NSHTTPCookie* cookie) {
return creation_time_manager_->GetCreationTime(cookie);
}
NSArray* SystemCookieStore::GetAllCookies() {
return GetAllCookies(/* manager = */ nullptr);
base::WeakPtr<SystemCookieStore> SystemCookieStore::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
// protected static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment