diff options
author | henrika <henrika@chromium.org> | 2015-05-15 04:13:24 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-15 11:13:31 +0000 |
commit | ac4f49641d2b1246fdcfdb35993b21200d43460f (patch) | |
tree | e68d46fb77bf2133d100b9b17f375d6129921077 /net | |
parent | 3b81bc1ac3ea712d448562dbcd7f5b35b58dbcf3 (diff) | |
download | chromium_src-ac4f49641d2b1246fdcfdb35993b21200d43460f.zip chromium_src-ac4f49641d2b1246fdcfdb35993b21200d43460f.tar.gz chromium_src-ac4f49641d2b1246fdcfdb35993b21200d43460f.tar.bz2 |
Revert of Moves SQLitePersistentCookieStore to net/extras/sqlite. (patchset #25 id:470001 of https://codereview.chromium.org/1016643004/)
Reason for revert:
Seems to break content_unittests QuotaPolicyCookieStoreTest.TestPolicy. See https://build.chromium.org/p/chromium.webrtc/builders/Win7%20Tester for details.
Reverting to see if the bot turns green again. I am unable to find any other CL that can cause this.
Original issue's description:
> Moves SQLitePersistentCookieStore to net/extras/sqlite.
>
> The application of special storage policy is split out into a new class,
> QuotaPolicyCookieStore, in content/browser/net.
>
> BUG=467596
> TEST=No visible impact.
>
> Committed: https://crrev.com/57adf29fb4e46a49272610140b097f85e1e805f5
> Cr-Commit-Position: refs/heads/master@{#329950}
TBR=rsleevi@chromium.org,mef@chromium.org,nharper@chromium.org,avi@chromium.org,rohitrao@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=467596
Review URL: https://codereview.chromium.org/1134113007
Cr-Commit-Position: refs/heads/master@{#330075}
Diffstat (limited to 'net')
-rw-r--r-- | net/BUILD.gn | 2 | ||||
-rw-r--r-- | net/extras/sqlite/sqlite_persistent_cookie_store.cc | 1366 | ||||
-rw-r--r-- | net/extras/sqlite/sqlite_persistent_cookie_store.h | 73 | ||||
-rw-r--r-- | net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc | 141 | ||||
-rw-r--r-- | net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc | 663 | ||||
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/net.gypi | 3 |
7 files changed, 0 insertions, 2250 deletions
diff --git a/net/BUILD.gn b/net/BUILD.gn index b4b3788..70f5999 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -1588,7 +1588,6 @@ executable("net_perftests") { sources = [ "cookies/cookie_monster_perftest.cc", "disk_cache/blockfile/disk_cache_perftest.cc", - "extras/sqlite/sqlite_persistent_cookie_store_perftest.cc", "proxy/proxy_resolver_perftest.cc", "udp/udp_socket_perftest.cc", ] @@ -1601,7 +1600,6 @@ executable("net_perftests") { "//base/test:test_support_perf", "//testing/gtest", "//url", - ":extras", ":net", ":test_support", ] diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc deleted file mode 100644 index 9fdb070..0000000 --- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ /dev/null @@ -1,1366 +0,0 @@ -// Copyright (c) 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 "net/extras/sqlite/sqlite_persistent_cookie_store.h" - -#include <map> -#include <set> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" -#include "base/profiler/scoped_tracker.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/lock.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/time/time.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/cookies/canonical_cookie.h" -#include "net/cookies/cookie_constants.h" -#include "net/cookies/cookie_util.h" -#include "net/extras/sqlite/cookie_crypto_delegate.h" -#include "sql/error_delegate_util.h" -#include "sql/meta_table.h" -#include "sql/statement.h" -#include "sql/transaction.h" -#include "url/gurl.h" - -using base::Time; - -namespace { - -// The persistent cookie store is loaded into memory on eTLD at a time. This -// variable controls the delay between loading eTLDs, so as to not overload the -// CPU or I/O with these low priority requests immediately after start up. -const int kLoadDelayMilliseconds = 0; - -} // namespace - -namespace net { - -// This class is designed to be shared between any client thread and the -// background task runner. It batches operations and commits them on a timer. -// -// SQLitePersistentCookieStore::Load is called to load all cookies. It -// delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread -// task to the background runner. This task calls Backend::ChainLoadCookies(), -// which repeatedly posts itself to the BG runner to load each eTLD+1's cookies -// in separate tasks. When this is complete, Backend::CompleteLoadOnIOThread is -// posted to the client runner, which notifies the caller of -// SQLitePersistentCookieStore::Load that the load is complete. -// -// If a priority load request is invoked via SQLitePersistentCookieStore:: -// LoadCookiesForKey, it is delegated to Backend::LoadCookiesForKey, which posts -// Backend::LoadKeyAndNotifyOnDBThread to the BG runner. That routine loads just -// that single domain key (eTLD+1)'s cookies, and posts a Backend:: -// CompleteLoadForKeyOnIOThread to the client runner to notify the caller of -// SQLitePersistentCookieStore::LoadCookiesForKey that that load is complete. -// -// Subsequent to loading, mutations may be queued by any thread using -// AddCookie, UpdateCookieAccessTime, and DeleteCookie. These are flushed to -// disk on the BG runner every 30 seconds, 512 operations, or call to Flush(), -// whichever occurs first. -class SQLitePersistentCookieStore::Backend - : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { - public: - Backend( - const base::FilePath& path, - const scoped_refptr<base::SequencedTaskRunner>& client_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, - bool restore_old_session_cookies, - CookieCryptoDelegate* crypto_delegate) - : path_(path), - num_pending_(0), - initialized_(false), - corruption_detected_(false), - restore_old_session_cookies_(restore_old_session_cookies), - num_cookies_read_(0), - client_task_runner_(client_task_runner), - background_task_runner_(background_task_runner), - num_priority_waiting_(0), - total_priority_requests_(0), - crypto_(crypto_delegate) {} - - // Creates or loads the SQLite database. - void Load(const LoadedCallback& loaded_callback); - - // Loads cookies for the domain key (eTLD+1). - void LoadCookiesForKey(const std::string& domain, - const LoadedCallback& loaded_callback); - - // Steps through all results of |smt|, makes a cookie from each, and adds the - // cookie to |cookies|. This method also updates |num_cookies_read_|. - void MakeCookiesFromSQLStatement(std::vector<CanonicalCookie*>* cookies, - sql::Statement* statement); - - // Batch a cookie addition. - void AddCookie(const CanonicalCookie& cc); - - // Batch a cookie access time update. - void UpdateCookieAccessTime(const CanonicalCookie& cc); - - // Batch a cookie deletion. - void DeleteCookie(const CanonicalCookie& cc); - - // Commit pending operations as soon as possible. - void Flush(const base::Closure& callback); - - // Commit any pending operations and close the database. This must be called - // before the object is destructed. - void Close(); - - // Post background delete of all cookies that match |cookies|. - void DeleteAllInList(const std::list<CookieOrigin>& cookies); - - private: - friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; - - // You should call Close() before destructing this object. - ~Backend() { - DCHECK(!db_.get()) << "Close should have already been called."; - DCHECK_EQ(0u, num_pending_); - DCHECK(pending_.empty()); - - for (CanonicalCookie* cookie : cookies_) { - delete cookie; - } - } - - // Database upgrade statements. - bool EnsureDatabaseVersion(); - - class PendingOperation { - public: - enum OperationType { - COOKIE_ADD, - COOKIE_UPDATEACCESS, - COOKIE_DELETE, - }; - - PendingOperation(OperationType op, const CanonicalCookie& cc) - : op_(op), cc_(cc) {} - - OperationType op() const { return op_; } - const CanonicalCookie& cc() const { return cc_; } - - private: - OperationType op_; - CanonicalCookie cc_; - }; - - private: - // Creates or loads the SQLite database on background runner. - void LoadAndNotifyInBackground(const LoadedCallback& loaded_callback, - const base::Time& posted_at); - - // Loads cookies for the domain key (eTLD+1) on background runner. - void LoadKeyAndNotifyInBackground(const std::string& domains, - const LoadedCallback& loaded_callback, - const base::Time& posted_at); - - // Notifies the CookieMonster when loading completes for a specific domain key - // or for all domain keys. Triggers the callback and passes it all cookies - // that have been loaded from DB since last IO notification. - void Notify(const LoadedCallback& loaded_callback, bool load_success); - - // Sends notification when the entire store is loaded, and reports metrics - // for the total time to load and aggregated results from any priority loads - // that occurred. - void CompleteLoadInForeground(const LoadedCallback& loaded_callback, - bool load_success); - - // Sends notification when a single priority load completes. Updates priority - // load metric data. The data is sent only after the final load completes. - void CompleteLoadForKeyInForeground(const LoadedCallback& loaded_callback, - bool load_success, - const base::Time& requested_at); - - // Sends all metrics, including posting a ReportMetricsInBackground task. - // Called after all priority and regular loading is complete. - void ReportMetrics(); - - // Sends background-runner owned metrics (i.e., the combined duration of all - // BG-runner tasks). - void ReportMetricsInBackground(); - - // Initialize the data base. - bool InitializeDatabase(); - - // Loads cookies for the next domain key from the DB, then either reschedules - // itself or schedules the provided callback to run on the client runner (if - // all domains are loaded). - void ChainLoadCookies(const LoadedCallback& loaded_callback); - - // Load all cookies for a set of domains/hosts - bool LoadCookiesForDomains(const std::set<std::string>& key); - - // Batch a cookie operation (add or delete) - void BatchOperation(PendingOperation::OperationType op, - const CanonicalCookie& cc); - // Commit our pending operations to the database. - void Commit(); - // Close() executed on the background runner. - void InternalBackgroundClose(); - - void DeleteSessionCookiesOnStartup(); - - void BackgroundDeleteAllInList(const std::list<CookieOrigin>& cookies); - - void DatabaseErrorCallback(int error, sql::Statement* stmt); - void KillDatabase(); - - void PostBackgroundTask(const tracked_objects::Location& origin, - const base::Closure& task); - void PostClientTask(const tracked_objects::Location& origin, - const base::Closure& task); - - // Shared code between the different load strategies to be used after all - // cookies have been loaded. - void FinishedLoadingCookies(const LoadedCallback& loaded_callback, - bool success); - - const base::FilePath path_; - scoped_ptr<sql::Connection> db_; - sql::MetaTable meta_table_; - - typedef std::list<PendingOperation*> PendingOperationsList; - PendingOperationsList pending_; - PendingOperationsList::size_type num_pending_; - // Guard |cookies_|, |pending_|, |num_pending_|. - base::Lock lock_; - - // Temporary buffer for cookies loaded from DB. Accumulates cookies to reduce - // the number of messages sent to the client runner. Sent back in response to - // individual load requests for domain keys or when all loading completes. - // Ownership of the cookies in this vector is transferred to the client in - // response to individual load requests or when all loading completes. - std::vector<CanonicalCookie*> cookies_; - - // Map of domain keys(eTLD+1) to domains/hosts that are to be loaded from DB. - std::map<std::string, std::set<std::string>> keys_to_load_; - - // Indicates if DB has been initialized. - bool initialized_; - - // Indicates if the kill-database callback has been scheduled. - bool corruption_detected_; - - // If false, we should filter out session cookies when reading the DB. - bool restore_old_session_cookies_; - - // The cumulative time spent loading the cookies on the background runner. - // Incremented and reported from the background runner. - base::TimeDelta cookie_load_duration_; - - // The total number of cookies read. Incremented and reported on the - // background runner. - int num_cookies_read_; - - scoped_refptr<base::SequencedTaskRunner> client_task_runner_; - scoped_refptr<base::SequencedTaskRunner> background_task_runner_; - - // Guards the following metrics-related properties (only accessed when - // starting/completing priority loads or completing the total load). - base::Lock metrics_lock_; - int num_priority_waiting_; - // The total number of priority requests. - int total_priority_requests_; - // The time when |num_priority_waiting_| incremented to 1. - base::Time current_priority_wait_start_; - // The cumulative duration of time when |num_priority_waiting_| was greater - // than 1. - base::TimeDelta priority_wait_duration_; - // Class with functions that do cryptographic operations (for protecting - // cookies stored persistently). - // - // Not owned. - CookieCryptoDelegate* crypto_; - - DISALLOW_COPY_AND_ASSIGN(Backend); -}; - -namespace { - -// Version number of the database. -// -// Version 9 adds a partial index to track non-persistent cookies. -// Non-persistent cookies sometimes need to be deleted on startup. There are -// frequently few or no non-persistent cookies, so the partial index allows the -// deletion to be sped up or skipped, without having to page in the DB. -// -// Version 8 adds "first-party only" cookies. -// -// Version 7 adds encrypted values. Old values will continue to be used but -// all new values written will be encrypted on selected operating systems. New -// records read by old clients will simply get an empty cookie value while old -// records read by new clients will continue to operate with the unencrypted -// version. New and old clients alike will always write/update records with -// what they support. -// -// Version 6 adds cookie priorities. This allows developers to influence the -// order in which cookies are evicted in order to meet domain cookie limits. -// -// Version 5 adds the columns has_expires and is_persistent, so that the -// database can store session cookies as well as persistent cookies. Databases -// of version 5 are incompatible with older versions of code. If a database of -// version 5 is read by older code, session cookies will be treated as normal -// cookies. Currently, these fields are written, but not read anymore. -// -// In version 4, we migrated the time epoch. If you open the DB with an older -// version on Mac or Linux, the times will look wonky, but the file will likely -// be usable. On Windows version 3 and 4 are the same. -// -// Version 3 updated the database to include the last access time, so we can -// expire them in decreasing order of use when we've reached the maximum -// number of cookies. -const int kCurrentVersionNumber = 9; -const int kCompatibleVersionNumber = 5; - -// Possible values for the 'priority' column. -enum DBCookiePriority { - kCookiePriorityLow = 0, - kCookiePriorityMedium = 1, - kCookiePriorityHigh = 2, -}; - -DBCookiePriority CookiePriorityToDBCookiePriority(CookiePriority value) { - switch (value) { - case COOKIE_PRIORITY_LOW: - return kCookiePriorityLow; - case COOKIE_PRIORITY_MEDIUM: - return kCookiePriorityMedium; - case COOKIE_PRIORITY_HIGH: - return kCookiePriorityHigh; - } - - NOTREACHED(); - return kCookiePriorityMedium; -} - -CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) { - switch (value) { - case kCookiePriorityLow: - return COOKIE_PRIORITY_LOW; - case kCookiePriorityMedium: - return COOKIE_PRIORITY_MEDIUM; - case kCookiePriorityHigh: - return COOKIE_PRIORITY_HIGH; - } - - NOTREACHED(); - return COOKIE_PRIORITY_DEFAULT; -} - -// Increments a specified TimeDelta by the duration between this object's -// constructor and destructor. Not thread safe. Multiple instances may be -// created with the same delta instance as long as their lifetimes are nested. -// The shortest lived instances have no impact. -class IncrementTimeDelta { - public: - explicit IncrementTimeDelta(base::TimeDelta* delta) - : delta_(delta), original_value_(*delta), start_(base::Time::Now()) {} - - ~IncrementTimeDelta() { - *delta_ = original_value_ + base::Time::Now() - start_; - } - - private: - base::TimeDelta* delta_; - base::TimeDelta original_value_; - base::Time start_; - - DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta); -}; - -// Initializes the cookies table, returning true on success. -bool InitTable(sql::Connection* db) { - if (db->DoesTableExist("cookies")) - return true; - - std::string stmt(base::StringPrintf( - "CREATE TABLE cookies (" - "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," - "host_key TEXT NOT NULL," - "name TEXT NOT NULL," - "value TEXT NOT NULL," - "path TEXT NOT NULL," - "expires_utc INTEGER NOT NULL," - "secure INTEGER NOT NULL," - "httponly INTEGER NOT NULL," - "last_access_utc INTEGER NOT NULL, " - "has_expires INTEGER NOT NULL DEFAULT 1, " - "persistent INTEGER NOT NULL DEFAULT 1," - "priority INTEGER NOT NULL DEFAULT %d," - "encrypted_value BLOB DEFAULT ''," - "firstpartyonly INTEGER NOT NULL DEFAULT 0)", - CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT))); - if (!db->Execute(stmt.c_str())) - return false; - - if (!db->Execute("CREATE INDEX domain ON cookies(host_key)")) - return false; - -#if defined(OS_IOS) - // iOS 8.1 and older doesn't support partial indices. iOS 8.2 supports - // partial indices. - if (!db->Execute("CREATE INDEX is_transient ON cookies(persistent)")) { -#else - if (!db->Execute( - "CREATE INDEX is_transient ON cookies(persistent) " - "where persistent != 1")) { -#endif - return false; - } - - return true; -} - -} // namespace - -void SQLitePersistentCookieStore::Backend::Load( - const LoadedCallback& loaded_callback) { - PostBackgroundTask(FROM_HERE, - base::Bind(&Backend::LoadAndNotifyInBackground, this, - loaded_callback, base::Time::Now())); -} - -void SQLitePersistentCookieStore::Backend::LoadCookiesForKey( - const std::string& key, - const LoadedCallback& loaded_callback) { - { - base::AutoLock locked(metrics_lock_); - if (num_priority_waiting_ == 0) - current_priority_wait_start_ = base::Time::Now(); - num_priority_waiting_++; - total_priority_requests_++; - } - - PostBackgroundTask( - FROM_HERE, base::Bind(&Backend::LoadKeyAndNotifyInBackground, this, key, - loaded_callback, base::Time::Now())); -} - -void SQLitePersistentCookieStore::Backend::LoadAndNotifyInBackground( - const LoadedCallback& loaded_callback, - const base::Time& posted_at) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - IncrementTimeDelta increment(&cookie_load_duration_); - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoadDBQueueWait", - base::Time::Now() - posted_at, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - if (!InitializeDatabase()) { - PostClientTask(FROM_HERE, base::Bind(&Backend::CompleteLoadInForeground, - this, loaded_callback, false)); - } else { - ChainLoadCookies(loaded_callback); - } -} - -void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground( - const std::string& key, - const LoadedCallback& loaded_callback, - const base::Time& posted_at) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - IncrementTimeDelta increment(&cookie_load_duration_); - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadDBQueueWait", - base::Time::Now() - posted_at, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - bool success = false; - if (InitializeDatabase()) { - std::map<std::string, std::set<std::string>>::iterator it = - keys_to_load_.find(key); - if (it != keys_to_load_.end()) { - success = LoadCookiesForDomains(it->second); - keys_to_load_.erase(it); - } else { - success = true; - } - } - - PostClientTask( - FROM_HERE, - base::Bind( - &SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground, - this, loaded_callback, success, posted_at)); -} - -void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground( - const LoadedCallback& loaded_callback, - bool load_success, - const ::Time& requested_at) { - DCHECK(client_task_runner_->RunsTasksOnCurrentThread()); - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadTotalWait", - base::Time::Now() - requested_at, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - Notify(loaded_callback, load_success); - - { - base::AutoLock locked(metrics_lock_); - num_priority_waiting_--; - if (num_priority_waiting_ == 0) { - priority_wait_duration_ += - base::Time::Now() - current_priority_wait_start_; - } - } -} - -void SQLitePersistentCookieStore::Backend::ReportMetricsInBackground() { - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoad", cookie_load_duration_, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); -} - -void SQLitePersistentCookieStore::Backend::ReportMetrics() { - PostBackgroundTask( - FROM_HERE, - base::Bind( - &SQLitePersistentCookieStore::Backend::ReportMetricsInBackground, - this)); - - { - base::AutoLock locked(metrics_lock_); - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.PriorityBlockingTime", - priority_wait_duration_, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - UMA_HISTOGRAM_COUNTS_100("Cookie.PriorityLoadCount", - total_priority_requests_); - - UMA_HISTOGRAM_COUNTS_10000("Cookie.NumberOfLoadedCookies", - num_cookies_read_); - } -} - -void SQLitePersistentCookieStore::Backend::CompleteLoadInForeground( - const LoadedCallback& loaded_callback, - bool load_success) { - Notify(loaded_callback, load_success); - - if (load_success) - ReportMetrics(); -} - -void SQLitePersistentCookieStore::Backend::Notify( - const LoadedCallback& loaded_callback, - bool load_success) { - DCHECK(client_task_runner_->RunsTasksOnCurrentThread()); - - std::vector<CanonicalCookie*> cookies; - { - base::AutoLock locked(lock_); - cookies.swap(cookies_); - } - - loaded_callback.Run(cookies); -} - -bool SQLitePersistentCookieStore::Backend::InitializeDatabase() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - if (initialized_ || corruption_detected_) { - // Return false if we were previously initialized but the DB has since been - // closed, or if corruption caused a database reset during initialization. - return db_ != NULL; - } - - base::Time start = base::Time::Now(); - - const base::FilePath dir = path_.DirName(); - if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { - return false; - } - - int64 db_size = 0; - if (base::GetFileSize(path_, &db_size)) - UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024); - - db_.reset(new sql::Connection); - db_->set_histogram_tag("Cookie"); - - // Unretained to avoid a ref loop with |db_|. - db_->set_error_callback( - base::Bind(&SQLitePersistentCookieStore::Backend::DatabaseErrorCallback, - base::Unretained(this))); - - if (!db_->Open(path_)) { - NOTREACHED() << "Unable to open cookie DB."; - if (corruption_detected_) - db_->Raze(); - meta_table_.Reset(); - db_.reset(); - return false; - } - - if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { - NOTREACHED() << "Unable to open cookie DB."; - if (corruption_detected_) - db_->Raze(); - meta_table_.Reset(); - db_.reset(); - return false; - } - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeInitializeDB", - base::Time::Now() - start, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - start = base::Time::Now(); - - // Retrieve all the domains - sql::Statement smt( - db_->GetUniqueStatement("SELECT DISTINCT host_key FROM cookies")); - - if (!smt.is_valid()) { - if (corruption_detected_) - db_->Raze(); - meta_table_.Reset(); - db_.reset(); - return false; - } - - std::vector<std::string> host_keys; - while (smt.Step()) - host_keys.push_back(smt.ColumnString(0)); - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoadDomains", - base::Time::Now() - start, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - base::Time start_parse = base::Time::Now(); - - // Build a map of domain keys (always eTLD+1) to domains. - for (size_t idx = 0; idx < host_keys.size(); ++idx) { - const std::string& domain = host_keys[idx]; - std::string key = registry_controlled_domains::GetDomainAndRegistry( - domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - - keys_to_load_[key].insert(domain); - } - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeParseDomains", - base::Time::Now() - start_parse, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeInitializeDomainMap", - base::Time::Now() - start, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - - initialized_ = true; - - if (!restore_old_session_cookies_) - DeleteSessionCookiesOnStartup(); - return true; -} - -void SQLitePersistentCookieStore::Backend::ChainLoadCookies( - const LoadedCallback& loaded_callback) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - IncrementTimeDelta increment(&cookie_load_duration_); - - bool load_success = true; - - if (!db_) { - // Close() has been called on this store. - load_success = false; - } else if (keys_to_load_.size() > 0) { - // Load cookies for the first domain key. - std::map<std::string, std::set<std::string>>::iterator it = - keys_to_load_.begin(); - load_success = LoadCookiesForDomains(it->second); - keys_to_load_.erase(it); - } - - // If load is successful and there are more domain keys to be loaded, - // then post a background task to continue chain-load; - // Otherwise notify on client runner. - if (load_success && keys_to_load_.size() > 0) { - bool success = background_task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&Backend::ChainLoadCookies, this, loaded_callback), - base::TimeDelta::FromMilliseconds(kLoadDelayMilliseconds)); - if (!success) { - LOG(WARNING) << "Failed to post task from " << FROM_HERE.ToString() - << " to background_task_runner_."; - } - } else { - FinishedLoadingCookies(loaded_callback, load_success); - } -} - -bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( - const std::set<std::string>& domains) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - sql::Statement smt; - if (restore_old_session_cookies_) { - smt.Assign(db_->GetCachedStatement( - SQL_FROM_HERE, - "SELECT creation_utc, host_key, name, value, encrypted_value, path, " - "expires_utc, secure, httponly, firstpartyonly, last_access_utc, " - "has_expires, persistent, priority FROM cookies WHERE host_key = ?")); - } else { - smt.Assign(db_->GetCachedStatement( - SQL_FROM_HERE, - "SELECT creation_utc, host_key, name, value, encrypted_value, path, " - "expires_utc, secure, httponly, firstpartyonly, last_access_utc, " - "has_expires, persistent, priority FROM cookies WHERE host_key = ? " - "AND persistent = 1")); - } - if (!smt.is_valid()) { - smt.Clear(); // Disconnect smt_ref from db_. - meta_table_.Reset(); - db_.reset(); - return false; - } - - std::vector<CanonicalCookie*> cookies; - std::set<std::string>::const_iterator it = domains.begin(); - for (; it != domains.end(); ++it) { - smt.BindString(0, *it); - MakeCookiesFromSQLStatement(&cookies, &smt); - smt.Reset(true); - } - { - base::AutoLock locked(lock_); - cookies_.insert(cookies_.end(), cookies.begin(), cookies.end()); - } - return true; -} - -void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement( - std::vector<CanonicalCookie*>* cookies, - sql::Statement* statement) { - sql::Statement& smt = *statement; - while (smt.Step()) { - std::string value; - std::string encrypted_value = smt.ColumnString(4); - if (!encrypted_value.empty() && crypto_) { - crypto_->DecryptString(encrypted_value, &value); - } else { - DCHECK(encrypted_value.empty()); - value = smt.ColumnString(3); - } - scoped_ptr<CanonicalCookie> cc(new CanonicalCookie( - // The "source" URL is not used with persisted cookies. - GURL(), // Source - smt.ColumnString(2), // name - value, // value - smt.ColumnString(1), // domain - smt.ColumnString(5), // path - Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc - Time::FromInternalValue(smt.ColumnInt64(6)), // expires_utc - Time::FromInternalValue(smt.ColumnInt64(10)), // last_access_utc - smt.ColumnInt(7) != 0, // secure - smt.ColumnInt(8) != 0, // httponly - smt.ColumnInt(9) != 0, // firstpartyonly - DBCookiePriorityToCookiePriority( - static_cast<DBCookiePriority>(smt.ColumnInt(13))))); // priority - DLOG_IF(WARNING, cc->CreationDate() > Time::Now()) - << L"CreationDate too recent"; - cookies->push_back(cc.release()); - ++num_cookies_read_; - } -} - -bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() { - // Version check. - if (!meta_table_.Init(db_.get(), kCurrentVersionNumber, - kCompatibleVersionNumber)) { - return false; - } - - if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { - LOG(WARNING) << "Cookie database is too new."; - return false; - } - - int cur_version = meta_table_.GetVersionNumber(); - if (cur_version == 2) { - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - if (!db_->Execute( - "ALTER TABLE cookies ADD COLUMN last_access_utc " - "INTEGER DEFAULT 0") || - !db_->Execute("UPDATE cookies SET last_access_utc = creation_utc")) { - LOG(WARNING) << "Unable to update cookie database to version 3."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - } - - if (cur_version == 3) { - // The time epoch changed for Mac & Linux in this version to match Windows. - // This patch came after the main epoch change happened, so some - // developers have "good" times for cookies added by the more recent - // versions. So we have to be careful to only update times that are under - // the old system (which will appear to be from before 1970 in the new - // system). The magic number used below is 1970 in our time units. - sql::Transaction transaction(db_.get()); - transaction.Begin(); -#if !defined(OS_WIN) - ignore_result(db_->Execute( - "UPDATE cookies " - "SET creation_utc = creation_utc + 11644473600000000 " - "WHERE rowid IN " - "(SELECT rowid FROM cookies WHERE " - "creation_utc > 0 AND creation_utc < 11644473600000000)")); - ignore_result(db_->Execute( - "UPDATE cookies " - "SET expires_utc = expires_utc + 11644473600000000 " - "WHERE rowid IN " - "(SELECT rowid FROM cookies WHERE " - "expires_utc > 0 AND expires_utc < 11644473600000000)")); - ignore_result(db_->Execute( - "UPDATE cookies " - "SET last_access_utc = last_access_utc + 11644473600000000 " - "WHERE rowid IN " - "(SELECT rowid FROM cookies WHERE " - "last_access_utc > 0 AND last_access_utc < 11644473600000000)")); -#endif - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - transaction.Commit(); - } - - if (cur_version == 4) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - if (!db_->Execute( - "ALTER TABLE cookies " - "ADD COLUMN has_expires INTEGER DEFAULT 1") || - !db_->Execute( - "ALTER TABLE cookies " - "ADD COLUMN persistent INTEGER DEFAULT 1")) { - LOG(WARNING) << "Unable to update cookie database to version 5."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV5", - base::TimeTicks::Now() - start_time); - } - - if (cur_version == 5) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - // Alter the table to add the priority column with a default value. - std::string stmt(base::StringPrintf( - "ALTER TABLE cookies ADD COLUMN priority INTEGER DEFAULT %d", - CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT))); - if (!db_->Execute(stmt.c_str())) { - LOG(WARNING) << "Unable to update cookie database to version 6."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV6", - base::TimeTicks::Now() - start_time); - } - - if (cur_version == 6) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - // Alter the table to add empty "encrypted value" column. - if (!db_->Execute( - "ALTER TABLE cookies " - "ADD COLUMN encrypted_value BLOB DEFAULT ''")) { - LOG(WARNING) << "Unable to update cookie database to version 7."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV7", - base::TimeTicks::Now() - start_time); - } - - if (cur_version == 7) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - // Alter the table to add a 'firstpartyonly' column. - if (!db_->Execute( - "ALTER TABLE cookies " - "ADD COLUMN firstpartyonly INTEGER DEFAULT 0")) { - LOG(WARNING) << "Unable to update cookie database to version 8."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV8", - base::TimeTicks::Now() - start_time); - } - - if (cur_version == 8) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return false; - - if (!db_->Execute("DROP INDEX IF EXISTS cookie_times")) { - LOG(WARNING) - << "Unable to drop table cookie_times in update to version 9."; - return false; - } - - if (!db_->Execute( - "CREATE INDEX IF NOT EXISTS domain ON cookies(host_key)")) { - LOG(WARNING) << "Unable to create index domain in update to version 9."; - return false; - } - -#if defined(OS_IOS) - // iOS 8.1 and older doesn't support partial indices. iOS 8.2 supports - // partial indices. - if (!db_->Execute( - "CREATE INDEX IF NOT EXISTS is_transient ON cookies(persistent)")) { -#else - if (!db_->Execute( - "CREATE INDEX IF NOT EXISTS is_transient ON cookies(persistent) " - "where persistent != 1")) { -#endif - LOG(WARNING) - << "Unable to create index is_transient in update to version 9."; - return false; - } - ++cur_version; - meta_table_.SetVersionNumber(cur_version); - meta_table_.SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)); - transaction.Commit(); - UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV9", - base::TimeTicks::Now() - start_time); - } - - // Put future migration cases here. - - if (cur_version < kCurrentVersionNumber) { - UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1); - - meta_table_.Reset(); - db_.reset(new sql::Connection); - if (!sql::Connection::Delete(path_) || !db_->Open(path_) || - !meta_table_.Init(db_.get(), kCurrentVersionNumber, - kCompatibleVersionNumber)) { - UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTableRecoveryFailed", 1); - NOTREACHED() << "Unable to reset the cookie DB."; - meta_table_.Reset(); - db_.reset(); - return false; - } - } - - return true; -} - -void SQLitePersistentCookieStore::Backend::AddCookie( - const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_ADD, cc); -} - -void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime( - const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc); -} - -void SQLitePersistentCookieStore::Backend::DeleteCookie( - const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_DELETE, cc); -} - -void SQLitePersistentCookieStore::Backend::BatchOperation( - PendingOperation::OperationType op, - const CanonicalCookie& cc) { - // Commit every 30 seconds. - static const int kCommitIntervalMs = 30 * 1000; - // Commit right away if we have more than 512 outstanding operations. - static const size_t kCommitAfterBatchSize = 512; - DCHECK(!background_task_runner_->RunsTasksOnCurrentThread()); - - // We do a full copy of the cookie here, and hopefully just here. - scoped_ptr<PendingOperation> po(new PendingOperation(op, cc)); - - PendingOperationsList::size_type num_pending; - { - base::AutoLock locked(lock_); - pending_.push_back(po.release()); - num_pending = ++num_pending_; - } - - if (num_pending == 1) { - // We've gotten our first entry for this batch, fire off the timer. - if (!background_task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&Backend::Commit, this), - base::TimeDelta::FromMilliseconds(kCommitIntervalMs))) { - NOTREACHED() << "background_task_runner_ is not running."; - } - } else if (num_pending == kCommitAfterBatchSize) { - // We've reached a big enough batch, fire off a commit now. - PostBackgroundTask(FROM_HERE, base::Bind(&Backend::Commit, this)); - } -} - -void SQLitePersistentCookieStore::Backend::Commit() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - PendingOperationsList ops; - { - base::AutoLock locked(lock_); - pending_.swap(ops); - num_pending_ = 0; - } - - // Maybe an old timer fired or we are already Close()'ed. - if (!db_.get() || ops.empty()) - return; - - sql::Statement add_smt(db_->GetCachedStatement( - SQL_FROM_HERE, - "INSERT INTO cookies (creation_utc, host_key, name, value, " - "encrypted_value, path, expires_utc, secure, httponly, firstpartyonly, " - "last_access_utc, has_expires, persistent, priority) " - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); - if (!add_smt.is_valid()) - return; - - sql::Statement update_access_smt(db_->GetCachedStatement( - SQL_FROM_HERE, - "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?")); - if (!update_access_smt.is_valid()) - return; - - sql::Statement del_smt(db_->GetCachedStatement( - SQL_FROM_HERE, "DELETE FROM cookies WHERE creation_utc=?")); - if (!del_smt.is_valid()) - return; - - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) - return; - - for (PendingOperationsList::iterator it = ops.begin(); it != ops.end(); - ++it) { - // Free the cookies as we commit them to the database. - scoped_ptr<PendingOperation> po(*it); - switch (po->op()) { - case PendingOperation::COOKIE_ADD: - add_smt.Reset(true); - add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue()); - add_smt.BindString(1, po->cc().Domain()); - add_smt.BindString(2, po->cc().Name()); - if (crypto_) { - std::string encrypted_value; - add_smt.BindCString(3, ""); // value - crypto_->EncryptString(po->cc().Value(), &encrypted_value); - // BindBlob() immediately makes an internal copy of the data. - add_smt.BindBlob(4, encrypted_value.data(), - static_cast<int>(encrypted_value.length())); - } else { - add_smt.BindString(3, po->cc().Value()); - add_smt.BindBlob(4, "", 0); // encrypted_value - } - add_smt.BindString(5, po->cc().Path()); - add_smt.BindInt64(6, po->cc().ExpiryDate().ToInternalValue()); - add_smt.BindInt(7, po->cc().IsSecure()); - add_smt.BindInt(8, po->cc().IsHttpOnly()); - add_smt.BindInt(9, po->cc().IsFirstPartyOnly()); - add_smt.BindInt64(10, po->cc().LastAccessDate().ToInternalValue()); - add_smt.BindInt(11, po->cc().IsPersistent()); - add_smt.BindInt(12, po->cc().IsPersistent()); - add_smt.BindInt(13, - CookiePriorityToDBCookiePriority(po->cc().Priority())); - if (!add_smt.Run()) - NOTREACHED() << "Could not add a cookie to the DB."; - break; - - case PendingOperation::COOKIE_UPDATEACCESS: - update_access_smt.Reset(true); - update_access_smt.BindInt64( - 0, po->cc().LastAccessDate().ToInternalValue()); - update_access_smt.BindInt64(1, - po->cc().CreationDate().ToInternalValue()); - if (!update_access_smt.Run()) - NOTREACHED() << "Could not update cookie last access time in the DB."; - break; - - case PendingOperation::COOKIE_DELETE: - del_smt.Reset(true); - del_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue()); - if (!del_smt.Run()) - NOTREACHED() << "Could not delete a cookie from the DB."; - break; - - default: - NOTREACHED(); - break; - } - } - bool succeeded = transaction.Commit(); - UMA_HISTOGRAM_ENUMERATION("Cookie.BackingStoreUpdateResults", - succeeded ? 0 : 1, 2); -} - -void SQLitePersistentCookieStore::Backend::Flush( - const base::Closure& callback) { - DCHECK(!background_task_runner_->RunsTasksOnCurrentThread()); - PostBackgroundTask(FROM_HERE, base::Bind(&Backend::Commit, this)); - - if (!callback.is_null()) { - // We want the completion task to run immediately after Commit() returns. - // Posting it from here means there is less chance of another task getting - // onto the message queue first, than if we posted it from Commit() itself. - PostBackgroundTask(FROM_HERE, callback); - } -} - -// Fire off a close message to the background runner. We could still have a -// pending commit timer or Load operations holding references on us, but if/when -// this fires we will already have been cleaned up and it will be ignored. -void SQLitePersistentCookieStore::Backend::Close() { - if (background_task_runner_->RunsTasksOnCurrentThread()) { - InternalBackgroundClose(); - } else { - // Must close the backend on the background runner. - PostBackgroundTask(FROM_HERE, - base::Bind(&Backend::InternalBackgroundClose, this)); - } -} - -void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - // Commit any pending operations - Commit(); - - meta_table_.Reset(); - db_.reset(); -} - -void SQLitePersistentCookieStore::Backend::DatabaseErrorCallback( - int error, - sql::Statement* stmt) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - if (!sql::IsErrorCatastrophic(error)) - return; - - // TODO(shess): Running KillDatabase() multiple times should be - // safe. - if (corruption_detected_) - return; - - corruption_detected_ = true; - - // Don't just do the close/delete here, as we are being called by |db| and - // that seems dangerous. - // TODO(shess): Consider just calling RazeAndClose() immediately. - // db_ may not be safe to reset at this point, but RazeAndClose() - // would cause the stack to unwind safely with errors. - PostBackgroundTask(FROM_HERE, base::Bind(&Backend::KillDatabase, this)); -} - -void SQLitePersistentCookieStore::Backend::KillDatabase() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - if (db_) { - // This Backend will now be in-memory only. In a future run we will recreate - // the database. Hopefully things go better then! - bool success = db_->RazeAndClose(); - UMA_HISTOGRAM_BOOLEAN("Cookie.KillDatabaseResult", success); - meta_table_.Reset(); - db_.reset(); - } -} - -void SQLitePersistentCookieStore::Backend::DeleteAllInList( - const std::list<CookieOrigin>& cookies) { - if (cookies.empty()) - return; - - // Perform deletion on background task runner. - background_task_runner_->PostTask( - FROM_HERE, - base::Bind(&Backend::BackgroundDeleteAllInList, this, cookies)); -} - -void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - base::Time start_time = base::Time::Now(); - if (!db_->Execute("DELETE FROM cookies WHERE persistent != 1")) - LOG(WARNING) << "Unable to delete session cookies."; - - UMA_HISTOGRAM_TIMES("Cookie.Startup.TimeSpentDeletingCookies", - base::Time::Now() - start_time); - UMA_HISTOGRAM_COUNTS("Cookie.Startup.NumberOfCookiesDeleted", - db_->GetLastChangeCount()); -} - -void SQLitePersistentCookieStore::Backend::BackgroundDeleteAllInList( - const std::list<CookieOrigin>& cookies) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - if (!db_) - return; - - // Force a commit of any pending writes before issuing deletes. - // TODO(rohitrao): Remove the need for this Commit() by instead pruning the - // list of pending operations. https://crbug.com/486742. - Commit(); - - sql::Statement del_smt(db_->GetCachedStatement( - SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key=? AND secure=?")); - if (!del_smt.is_valid()) { - LOG(WARNING) << "Unable to delete cookies on shutdown."; - return; - } - - sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) { - LOG(WARNING) << "Unable to delete cookies on shutdown."; - return; - } - - for (const auto& cookie : cookies) { - const GURL url(cookie_util::CookieOriginToURL(cookie.first, cookie.second)); - if (!url.is_valid()) - continue; - - del_smt.Reset(true); - del_smt.BindString(0, cookie.first); - del_smt.BindInt(1, cookie.second); - if (!del_smt.Run()) - NOTREACHED() << "Could not delete a cookie from the DB."; - } - - if (!transaction.Commit()) - LOG(WARNING) << "Unable to delete cookies on shutdown."; -} - -void SQLitePersistentCookieStore::Backend::PostBackgroundTask( - const tracked_objects::Location& origin, - const base::Closure& task) { - if (!background_task_runner_->PostTask(origin, task)) { - LOG(WARNING) << "Failed to post task from " << origin.ToString() - << " to background_task_runner_."; - } -} - -void SQLitePersistentCookieStore::Backend::PostClientTask( - const tracked_objects::Location& origin, - const base::Closure& task) { - if (!client_task_runner_->PostTask(origin, task)) { - LOG(WARNING) << "Failed to post task from " << origin.ToString() - << " to client_task_runner_."; - } -} - -void SQLitePersistentCookieStore::Backend::FinishedLoadingCookies( - const LoadedCallback& loaded_callback, - bool success) { - PostClientTask(FROM_HERE, base::Bind(&Backend::CompleteLoadInForeground, this, - loaded_callback, success)); -} - -SQLitePersistentCookieStore::SQLitePersistentCookieStore( - const base::FilePath& path, - const scoped_refptr<base::SequencedTaskRunner>& client_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, - bool restore_old_session_cookies, - CookieCryptoDelegate* crypto_delegate) - : backend_(new Backend(path, - client_task_runner, - background_task_runner, - restore_old_session_cookies, - crypto_delegate)) { -} - -void SQLitePersistentCookieStore::DeleteAllInList( - const std::list<CookieOrigin>& cookies) { - backend_->DeleteAllInList(cookies); -} - -void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) { - backend_->Load(loaded_callback); -} - -void SQLitePersistentCookieStore::LoadCookiesForKey( - const std::string& key, - const LoadedCallback& loaded_callback) { - backend_->LoadCookiesForKey(key, loaded_callback); -} - -void SQLitePersistentCookieStore::AddCookie(const CanonicalCookie& cc) { - backend_->AddCookie(cc); -} - -void SQLitePersistentCookieStore::UpdateCookieAccessTime( - const CanonicalCookie& cc) { - backend_->UpdateCookieAccessTime(cc); -} - -void SQLitePersistentCookieStore::DeleteCookie(const CanonicalCookie& cc) { - backend_->DeleteCookie(cc); -} - -void SQLitePersistentCookieStore::SetForceKeepSessionState() { - // This store never discards session-only cookies, so this call has no effect. -} - -void SQLitePersistentCookieStore::Flush(const base::Closure& callback) { - backend_->Flush(callback); -} - -SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { - backend_->Close(); - // We release our reference to the Backend, though it will probably still have - // a reference if the background runner has not run Close() yet. -} - -} // namespace net diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.h b/net/extras/sqlite/sqlite_persistent_cookie_store.h deleted file mode 100644 index e29471a..0000000 --- a/net/extras/sqlite/sqlite_persistent_cookie_store.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 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. - -#ifndef NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_COOKIE_STORE_H_ -#define NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_COOKIE_STORE_H_ - -#include <list> -#include <string> -#include <utility> -#include <vector> - -#include "base/callback_forward.h" -#include "base/memory/ref_counted.h" -#include "net/cookies/cookie_monster.h" - -class Task; - -namespace base { -class FilePath; -class SequencedTaskRunner; -} // namespace base - -namespace net { -class CanonicalCookie; -class CookieCryptoDelegate; - -// Implements the PersistentCookieStore interface in terms of a SQLite database. -// For documentation about the actual member functions consult the documentation -// of the parent class |CookieMonster::PersistentCookieStore|. -class SQLitePersistentCookieStore - : public CookieMonster::PersistentCookieStore { - public: - // Contains the origin and a bool indicating whether or not the - // origin is secure. - typedef std::pair<std::string, bool> CookieOrigin; - - // All blocking database accesses will be performed on - // |background_task_runner|, while |client_task_runner| is used to invoke - // callbacks. - SQLitePersistentCookieStore( - const base::FilePath& path, - const scoped_refptr<base::SequencedTaskRunner>& client_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, - bool restore_old_session_cookies, - CookieCryptoDelegate* crypto_delegate); - - // Deletes the cookies whose origins match those given in |cookies|. - void DeleteAllInList(const std::list<CookieOrigin>& cookies); - - // CookieMonster::PersistentCookieStore: - void Load(const LoadedCallback& loaded_callback) override; - void LoadCookiesForKey(const std::string& key, - const LoadedCallback& callback) override; - void AddCookie(const CanonicalCookie& cc) override; - void UpdateCookieAccessTime(const CanonicalCookie& cc) override; - void DeleteCookie(const CanonicalCookie& cc) override; - void SetForceKeepSessionState() override; - void Flush(const base::Closure& callback) override; - - private: - ~SQLitePersistentCookieStore() override; - - class Backend; - - scoped_refptr<Backend> backend_; - - DISALLOW_COPY_AND_ASSIGN(SQLitePersistentCookieStore); -}; - -} // namespace net - -#endif // NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_COOKIE_STORE_H_ diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc deleted file mode 100644 index b149ac0..0000000 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 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 "net/extras/sqlite/sqlite_persistent_cookie_store.h" - -#include <vector> - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/perf_time_logger.h" -#include "base/test/sequenced_worker_pool_owner.h" -#include "base/threading/sequenced_worker_pool.h" -#include "net/cookies/canonical_cookie.h" -#include "net/cookies/cookie_constants.h" -#include "net/extras/sqlite/cookie_crypto_delegate.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -const base::FilePath::CharType cookie_filename[] = FILE_PATH_LITERAL("Cookies"); - -} // namespace - -class SQLitePersistentCookieStorePerfTest : public testing::Test { - public: - SQLitePersistentCookieStorePerfTest() - : pool_owner_(new base::SequencedWorkerPoolOwner(1, "Background Pool")), - loaded_event_(false, false), - key_loaded_event_(false, false) {} - - void OnLoaded(const std::vector<CanonicalCookie*>& cookies) { - cookies_ = cookies; - loaded_event_.Signal(); - } - - void OnKeyLoaded(const std::vector<CanonicalCookie*>& cookies) { - cookies_ = cookies; - key_loaded_event_.Signal(); - } - - void Load() { - store_->Load(base::Bind(&SQLitePersistentCookieStorePerfTest::OnLoaded, - base::Unretained(this))); - loaded_event_.Wait(); - } - - scoped_refptr<base::SequencedTaskRunner> background_task_runner() { - return pool_owner_->pool()->GetSequencedTaskRunner( - pool_owner_->pool()->GetNamedSequenceToken("background")); - } - - scoped_refptr<base::SequencedTaskRunner> client_task_runner() { - return pool_owner_->pool()->GetSequencedTaskRunner( - pool_owner_->pool()->GetNamedSequenceToken("client")); - } - - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(cookie_filename), client_task_runner(), - background_task_runner(), false, NULL); - std::vector<CanonicalCookie*> cookies; - Load(); - ASSERT_EQ(0u, cookies_.size()); - // Creates 15000 cookies from 300 eTLD+1s. - base::Time t = base::Time::Now(); - for (int domain_num = 0; domain_num < 300; domain_num++) { - std::string domain_name(base::StringPrintf(".domain_%d.com", domain_num)); - GURL gurl("www" + domain_name); - for (int cookie_num = 0; cookie_num < 50; ++cookie_num) { - t += base::TimeDelta::FromInternalValue(10); - store_->AddCookie(CanonicalCookie( - gurl, base::StringPrintf("Cookie_%d", cookie_num), "1", domain_name, - "/", t, t, t, false, false, false, COOKIE_PRIORITY_DEFAULT)); - } - } - // Replace the store effectively destroying the current one and forcing it - // to write its data to disk. - store_ = NULL; - - // Shut down the pool, causing deferred (no-op) commits to be discarded. - pool_owner_->pool()->Shutdown(); - // ~SequencedWorkerPoolOwner blocks on pool shutdown. - pool_owner_.reset(new base::SequencedWorkerPoolOwner(1, "pool")); - - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(cookie_filename), client_task_runner(), - background_task_runner(), false, NULL); - } - - void TearDown() override { - store_ = NULL; - pool_owner_->pool()->Shutdown(); - } - - protected: - base::MessageLoop main_loop_; - scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_; - base::WaitableEvent loaded_event_; - base::WaitableEvent key_loaded_event_; - std::vector<CanonicalCookie*> cookies_; - base::ScopedTempDir temp_dir_; - scoped_refptr<SQLitePersistentCookieStore> store_; -}; - -// Test the performance of priority load of cookies for a specfic domain key -TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadForKeyPerformance) { - for (int domain_num = 0; domain_num < 3; ++domain_num) { - std::string domain_name(base::StringPrintf("domain_%d.com", domain_num)); - base::PerfTimeLogger timer( - ("Load cookies for the eTLD+1 " + domain_name).c_str()); - store_->LoadCookiesForKey( - domain_name, - base::Bind(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded, - base::Unretained(this))); - key_loaded_event_.Wait(); - timer.Done(); - - ASSERT_EQ(50U, cookies_.size()); - } -} - -// Test the performance of load -TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadPerformance) { - base::PerfTimeLogger timer("Load all cookies"); - Load(); - timer.Done(); - - ASSERT_EQ(15000U, cookies_.size()); -} - -} // namespace net diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc deleted file mode 100644 index 6dc3810..0000000 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc +++ /dev/null @@ -1,663 +0,0 @@ -// Copyright (c) 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 "net/extras/sqlite/sqlite_persistent_cookie_store.h" - -#include <map> -#include <set> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "base/stl_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/sequenced_worker_pool_owner.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/time/time.h" -#include "crypto/encryptor.h" -#include "crypto/symmetric_key.h" -#include "net/cookies/canonical_cookie.h" -#include "net/cookies/cookie_constants.h" -#include "net/extras/sqlite/cookie_crypto_delegate.h" -#include "sql/connection.h" -#include "sql/meta_table.h" -#include "sql/statement.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies"); - -class CookieCryptor : public CookieCryptoDelegate { - public: - CookieCryptor(); - bool EncryptString(const std::string& plaintext, - std::string* ciphertext) override; - bool DecryptString(const std::string& ciphertext, - std::string* plaintext) override; - - private: - scoped_ptr<crypto::SymmetricKey> key_; - crypto::Encryptor encryptor_; -}; - -CookieCryptor::CookieCryptor() - : key_( - crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, - "password", - "saltiest", - 1000, - 256)) { - std::string iv("the iv: 16 bytes"); - encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv); -} - -bool CookieCryptor::EncryptString(const std::string& plaintext, - std::string* ciphertext) { - return encryptor_.Encrypt(plaintext, ciphertext); -} - -bool CookieCryptor::DecryptString(const std::string& ciphertext, - std::string* plaintext) { - return encryptor_.Decrypt(ciphertext, plaintext); -} - -} // namespace - -typedef std::vector<CanonicalCookie*> CanonicalCookieVector; - -class SQLitePersistentCookieStoreTest : public testing::Test { - public: - SQLitePersistentCookieStoreTest() - : pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")), - loaded_event_(false, false), - key_loaded_event_(false, false), - db_thread_event_(false, false) {} - - void OnLoaded(const CanonicalCookieVector& cookies) { - cookies_ = cookies; - loaded_event_.Signal(); - } - - void OnKeyLoaded(const CanonicalCookieVector& cookies) { - cookies_ = cookies; - key_loaded_event_.Signal(); - } - - void Load(CanonicalCookieVector* cookies) { - EXPECT_FALSE(loaded_event_.IsSignaled()); - store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this))); - loaded_event_.Wait(); - *cookies = cookies_; - } - - void Flush() { - base::WaitableEvent event(false, false); - store_->Flush( - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); - event.Wait(); - } - - scoped_refptr<base::SequencedTaskRunner> background_task_runner() { - return pool_owner_->pool()->GetSequencedTaskRunner( - pool_owner_->pool()->GetNamedSequenceToken("background")); - } - - scoped_refptr<base::SequencedTaskRunner> client_task_runner() { - return pool_owner_->pool()->GetSequencedTaskRunner( - pool_owner_->pool()->GetNamedSequenceToken("client")); - } - - void DestroyStore() { - store_ = nullptr; - // Make sure we wait until the destructor has run by shutting down the pool - // resetting the owner (whose destructor blocks on the pool completion). - pool_owner_->pool()->Shutdown(); - // Create a new pool for the few tests that create multiple stores. In other - // cases this is wasted but harmless. - pool_owner_.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool")); - } - - void CreateAndLoad(bool crypt_cookies, - bool restore_old_session_cookies, - CanonicalCookieVector* cookies) { - if (crypt_cookies) - cookie_crypto_delegate_.reset(new CookieCryptor()); - - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(kCookieFilename), client_task_runner(), - background_task_runner(), restore_old_session_cookies, - cookie_crypto_delegate_.get()); - Load(cookies); - } - - void InitializeStore(bool crypt, bool restore_old_session_cookies) { - CanonicalCookieVector cookies; - CreateAndLoad(crypt, restore_old_session_cookies, &cookies); - EXPECT_EQ(0U, cookies.size()); - } - - // We have to create this method to wrap WaitableEvent::Wait, since we cannot - // bind a non-void returning method as a Closure. - void WaitOnDBEvent() { db_thread_event_.Wait(); } - - // Adds a persistent cookie to store_. - void AddCookie(const std::string& name, - const std::string& value, - const std::string& domain, - const std::string& path, - const base::Time& creation) { - store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path, - creation, creation, creation, false, - false, false, COOKIE_PRIORITY_DEFAULT)); - } - - void AddCookieWithExpiration(const std::string& name, - const std::string& value, - const std::string& domain, - const std::string& path, - const base::Time& creation, - const base::Time& expiration) { - store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path, - creation, expiration, creation, false, - false, false, COOKIE_PRIORITY_DEFAULT)); - } - - std::string ReadRawDBContents() { - std::string contents; - if (!base::ReadFileToString(temp_dir_.path().Append(kCookieFilename), - &contents)) - return std::string(); - return contents; - } - - void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } - - void TearDown() override { - DestroyStore(); - pool_owner_->pool()->Shutdown(); - } - - protected: - scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_; - base::WaitableEvent loaded_event_; - base::WaitableEvent key_loaded_event_; - base::WaitableEvent db_thread_event_; - CanonicalCookieVector cookies_; - base::ScopedTempDir temp_dir_; - scoped_refptr<SQLitePersistentCookieStore> store_; - scoped_ptr<CookieCryptoDelegate> cookie_crypto_delegate_; -}; - -TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) { - InitializeStore(false, false); - AddCookie("A", "B", "foo.bar", "/", base::Time::Now()); - DestroyStore(); - - // Load up the store and verify that it has good data in it. - CanonicalCookieVector cookies; - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(1U, cookies.size()); - ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); - ASSERT_STREQ("A", cookies[0]->Name().c_str()); - ASSERT_STREQ("B", cookies[0]->Value().c_str()); - DestroyStore(); - STLDeleteElements(&cookies); - - // Now corrupt the meta table. - { - sql::Connection db; - ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename))); - sql::MetaTable meta_table_; - meta_table_.Init(&db, 1, 1); - ASSERT_TRUE(db.Execute("DELETE FROM meta")); - db.Close(); - } - - // Upon loading, the database should be reset to a good, blank state. - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(0U, cookies.size()); - - // Verify that, after, recovery, the database persists properly. - AddCookie("X", "Y", "foo.bar", "/", base::Time::Now()); - DestroyStore(); - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(1U, cookies.size()); - ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); - ASSERT_STREQ("X", cookies[0]->Name().c_str()); - ASSERT_STREQ("Y", cookies[0]->Value().c_str()); - STLDeleteElements(&cookies); -} - -// Test if data is stored as expected in the SQLite database. -TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) { - InitializeStore(false, false); - AddCookie("A", "B", "foo.bar", "/", base::Time::Now()); - // Replace the store effectively destroying the current one and forcing it - // to write its data to disk. Then we can see if after loading it again it - // is still there. - DestroyStore(); - // Reload and test for persistence - CanonicalCookieVector cookies; - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(1U, cookies.size()); - ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); - ASSERT_STREQ("A", cookies[0]->Name().c_str()); - ASSERT_STREQ("B", cookies[0]->Value().c_str()); - - // Now delete the cookie and check persistence again. - store_->DeleteCookie(*cookies[0]); - DestroyStore(); - STLDeleteElements(&cookies); - - // Reload and check if the cookie has been removed. - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(0U, cookies.size()); -} - -TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) { - // Initialize the cookie store with 3 persistent cookies, 5 transient - // cookies. - InitializeStore(false, false); - - // Add persistent cookies. - base::Time t = base::Time::Now(); - AddCookie("A", "B", "a1.com", "/", t); - t += base::TimeDelta::FromInternalValue(10); - AddCookie("A", "B", "a2.com", "/", t); - t += base::TimeDelta::FromInternalValue(10); - AddCookie("A", "B", "a3.com", "/", t); - - // Add transient cookies. - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "b1.com", "/", t, base::Time()); - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "b2.com", "/", t, base::Time()); - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "b3.com", "/", t, base::Time()); - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "b4.com", "/", t, base::Time()); - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "b5.com", "/", t, base::Time()); - DestroyStore(); - - // Load the store a second time. Before the store finishes loading, add a - // transient cookie and flush it to disk. - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(kCookieFilename), client_task_runner(), - background_task_runner(), false, nullptr); - - // Posting a blocking task to db_thread_ makes sure that the DB thread waits - // until both Load and Flush have been posted to its task queue. - background_task_runner()->PostTask( - FROM_HERE, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, - base::Unretained(this))); - store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this))); - t += base::TimeDelta::FromInternalValue(10); - AddCookieWithExpiration("A", "B", "c.com", "/", t, base::Time()); - base::WaitableEvent event(false, false); - store_->Flush( - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); - - // Now the DB-thread queue contains: - // (active:) - // 1. Wait (on db_event) - // (pending:) - // 2. "Init And Chain-Load First Domain" - // 3. Add Cookie (c.com) - // 4. Flush Cookie (c.com) - db_thread_event_.Signal(); - event.Wait(); - loaded_event_.Wait(); - STLDeleteElements(&cookies_); - DestroyStore(); - - // Load the store a third time, this time restoring session cookies. The - // store should contain exactly 4 cookies: the 3 persistent, and "c.com", - // which was added during the second cookie store load. - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(kCookieFilename), client_task_runner(), - background_task_runner(), true, nullptr); - store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this))); - loaded_event_.Wait(); - ASSERT_EQ(4u, cookies_.size()); - STLDeleteElements(&cookies_); -} - -// Test that priority load of cookies for a specfic domain key could be -// completed before the entire store is loaded -TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) { - InitializeStore(false, false); - base::Time t = base::Time::Now(); - AddCookie("A", "B", "foo.bar", "/", t); - t += base::TimeDelta::FromInternalValue(10); - AddCookie("A", "B", "www.aaa.com", "/", t); - t += base::TimeDelta::FromInternalValue(10); - AddCookie("A", "B", "travel.aaa.com", "/", t); - t += base::TimeDelta::FromInternalValue(10); - AddCookie("A", "B", "www.bbb.com", "/", t); - DestroyStore(); - - store_ = new SQLitePersistentCookieStore( - temp_dir_.path().Append(kCookieFilename), client_task_runner(), - background_task_runner(), false, nullptr); - - // Posting a blocking task to db_thread_ makes sure that the DB thread waits - // until both Load and LoadCookiesForKey have been posted to its task queue. - background_task_runner()->PostTask( - FROM_HERE, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, - base::Unretained(this))); - store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this))); - store_->LoadCookiesForKey( - "aaa.com", base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded, - base::Unretained(this))); - background_task_runner()->PostTask( - FROM_HERE, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, - base::Unretained(this))); - - // Now the DB-thread queue contains: - // (active:) - // 1. Wait (on db_event) - // (pending:) - // 2. "Init And Chain-Load First Domain" - // 3. Priority Load (aaa.com) - // 4. Wait (on db_event) - db_thread_event_.Signal(); - key_loaded_event_.Wait(); - ASSERT_EQ(loaded_event_.IsSignaled(), false); - std::set<std::string> cookies_loaded; - for (CanonicalCookieVector::const_iterator it = cookies_.begin(); - it != cookies_.end(); ++it) { - cookies_loaded.insert((*it)->Domain().c_str()); - } - STLDeleteElements(&cookies_); - ASSERT_GT(4U, cookies_loaded.size()); - ASSERT_EQ(true, cookies_loaded.find("www.aaa.com") != cookies_loaded.end()); - ASSERT_EQ(true, - cookies_loaded.find("travel.aaa.com") != cookies_loaded.end()); - - db_thread_event_.Signal(); - loaded_event_.Wait(); - for (CanonicalCookieVector::const_iterator it = cookies_.begin(); - it != cookies_.end(); ++it) { - cookies_loaded.insert((*it)->Domain().c_str()); - } - ASSERT_EQ(4U, cookies_loaded.size()); - ASSERT_EQ(cookies_loaded.find("foo.bar") != cookies_loaded.end(), true); - ASSERT_EQ(cookies_loaded.find("www.bbb.com") != cookies_loaded.end(), true); - STLDeleteElements(&cookies_); -} - -// Test that we can force the database to be written by calling Flush(). -TEST_F(SQLitePersistentCookieStoreTest, TestFlush) { - InitializeStore(false, false); - // File timestamps don't work well on all platforms, so we'll determine - // whether the DB file has been modified by checking its size. - base::FilePath path = temp_dir_.path().Append(kCookieFilename); - base::File::Info info; - ASSERT_TRUE(base::GetFileInfo(path, &info)); - int64 base_size = info.size; - - // Write some large cookies, so the DB will have to expand by several KB. - for (char c = 'a'; c < 'z'; ++c) { - // Each cookie needs a unique timestamp for creation_utc (see DB schema). - base::Time t = base::Time::Now() + base::TimeDelta::FromMicroseconds(c); - std::string name(1, c); - std::string value(1000, c); - AddCookie(name, value, "foo.bar", "/", t); - } - - Flush(); - - // We forced a write, so now the file will be bigger. - ASSERT_TRUE(base::GetFileInfo(path, &info)); - ASSERT_GT(info.size, base_size); -} - -// Test loading old session cookies from the disk. -TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) { - InitializeStore(false, true); - - // Add a session cookie. - store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/", - base::Time::Now(), base::Time(), - base::Time::Now(), false, false, false, - COOKIE_PRIORITY_DEFAULT)); - - // Force the store to write its data to the disk. - DestroyStore(); - - // Create a store that loads session cookies and test that the session cookie - // was loaded. - CanonicalCookieVector cookies; - CreateAndLoad(false, true, &cookies); - - ASSERT_EQ(1U, cookies.size()); - ASSERT_STREQ("sessioncookie.com", cookies[0]->Domain().c_str()); - ASSERT_STREQ("C", cookies[0]->Name().c_str()); - ASSERT_STREQ("D", cookies[0]->Value().c_str()); - ASSERT_EQ(COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority()); - - STLDeleteElements(&cookies); -} - -// Test loading old session cookies from the disk. -TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) { - InitializeStore(false, true); - - // Add a session cookie. - store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/", - base::Time::Now(), base::Time(), - base::Time::Now(), false, false, false, - COOKIE_PRIORITY_DEFAULT)); - - // Force the store to write its data to the disk. - DestroyStore(); - - // Create a store that doesn't load old session cookies and test that the - // session cookie was not loaded. - CanonicalCookieVector cookies; - CreateAndLoad(false, false, &cookies); - ASSERT_EQ(0U, cookies.size()); - - // The store should also delete the session cookie. Wait until that has been - // done. - DestroyStore(); - - // Create a store that loads old session cookies and test that the session - // cookie is gone. - CreateAndLoad(false, true, &cookies); - ASSERT_EQ(0U, cookies.size()); -} - -TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) { - InitializeStore(false, true); - static const char kSessionName[] = "session"; - static const char kPersistentName[] = "persistent"; - - // Add a session cookie. - store_->AddCookie(CanonicalCookie(GURL(), kSessionName, "val", - "sessioncookie.com", "/", base::Time::Now(), - base::Time(), base::Time::Now(), false, - false, false, COOKIE_PRIORITY_DEFAULT)); - // Add a persistent cookie. - store_->AddCookie(CanonicalCookie( - GURL(), kPersistentName, "val", "sessioncookie.com", "/", - base::Time::Now() - base::TimeDelta::FromDays(1), - base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), - false, false, false, COOKIE_PRIORITY_DEFAULT)); - - // Force the store to write its data to the disk. - DestroyStore(); - - // Create a store that loads session cookie and test that the IsPersistent - // attribute is restored. - CanonicalCookieVector cookies; - CreateAndLoad(false, true, &cookies); - ASSERT_EQ(2U, cookies.size()); - - std::map<std::string, CanonicalCookie*> cookie_map; - for (CanonicalCookieVector::const_iterator it = cookies.begin(); - it != cookies.end(); ++it) { - cookie_map[(*it)->Name()] = *it; - } - - std::map<std::string, CanonicalCookie*>::const_iterator it = - cookie_map.find(kSessionName); - ASSERT_TRUE(it != cookie_map.end()); - EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent()); - - it = cookie_map.find(kPersistentName); - ASSERT_TRUE(it != cookie_map.end()); - EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent()); - - STLDeleteElements(&cookies); -} - -TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) { - static const char kLowName[] = "low"; - static const char kMediumName[] = "medium"; - static const char kHighName[] = "high"; - static const char kCookieDomain[] = "sessioncookie.com"; - static const char kCookieValue[] = "value"; - static const char kCookiePath[] = "/"; - - InitializeStore(false, true); - - // Add a low-priority persistent cookie. - store_->AddCookie(CanonicalCookie( - GURL(), kLowName, kCookieValue, kCookieDomain, kCookiePath, - base::Time::Now() - base::TimeDelta::FromMinutes(1), - base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), - false, false, false, COOKIE_PRIORITY_LOW)); - - // Add a medium-priority persistent cookie. - store_->AddCookie(CanonicalCookie( - GURL(), kMediumName, kCookieValue, kCookieDomain, kCookiePath, - base::Time::Now() - base::TimeDelta::FromMinutes(2), - base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), - false, false, false, COOKIE_PRIORITY_MEDIUM)); - - // Add a high-priority peristent cookie. - store_->AddCookie(CanonicalCookie( - GURL(), kHighName, kCookieValue, kCookieDomain, kCookiePath, - base::Time::Now() - base::TimeDelta::FromMinutes(3), - base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), - false, false, false, COOKIE_PRIORITY_HIGH)); - - // Force the store to write its data to the disk. - DestroyStore(); - - // Create a store that loads session cookie and test that the priority - // attribute values are restored. - CanonicalCookieVector cookies; - CreateAndLoad(false, true, &cookies); - ASSERT_EQ(3U, cookies.size()); - - // Put the cookies into a map, by name, so we can easily find them. - std::map<std::string, CanonicalCookie*> cookie_map; - for (CanonicalCookieVector::const_iterator it = cookies.begin(); - it != cookies.end(); ++it) { - cookie_map[(*it)->Name()] = *it; - } - - // Validate that each cookie has the correct priority. - std::map<std::string, CanonicalCookie*>::const_iterator it = - cookie_map.find(kLowName); - ASSERT_TRUE(it != cookie_map.end()); - EXPECT_EQ(COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority()); - - it = cookie_map.find(kMediumName); - ASSERT_TRUE(it != cookie_map.end()); - EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority()); - - it = cookie_map.find(kHighName); - ASSERT_TRUE(it != cookie_map.end()); - EXPECT_EQ(COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority()); - - STLDeleteElements(&cookies); -} - -TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) { - CanonicalCookieVector cookies; - - // Create unencrypted cookie store and write something to it. - InitializeStore(false, false); - AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now()); - DestroyStore(); - - // Verify that "value" is visible in the file. This is necessary in order to - // have confidence in a later test that "encrypted_value" is not visible. - std::string contents = ReadRawDBContents(); - EXPECT_NE(0U, contents.length()); - EXPECT_NE(contents.find("value123XYZ"), std::string::npos); - - // Create encrypted cookie store and ensure old cookie still reads. - STLDeleteElements(&cookies_); - EXPECT_EQ(0U, cookies_.size()); - CreateAndLoad(true, false, &cookies); - EXPECT_EQ(1U, cookies_.size()); - EXPECT_EQ("name", cookies_[0]->Name()); - EXPECT_EQ("value123XYZ", cookies_[0]->Value()); - - // Make sure we can update existing cookie and add new cookie as encrypted. - store_->DeleteCookie(*(cookies_[0])); - AddCookie("name", "encrypted_value123XYZ", "foo.bar", "/", base::Time::Now()); - AddCookie("other", "something456ABC", "foo.bar", "/", - base::Time::Now() + base::TimeDelta::FromInternalValue(10)); - DestroyStore(); - STLDeleteElements(&cookies_); - CreateAndLoad(true, false, &cookies); - EXPECT_EQ(2U, cookies_.size()); - CanonicalCookie* cookie_name = nullptr; - CanonicalCookie* cookie_other = nullptr; - if (cookies_[0]->Name() == "name") { - cookie_name = cookies_[0]; - cookie_other = cookies_[1]; - } else { - cookie_name = cookies_[1]; - cookie_other = cookies_[0]; - } - EXPECT_EQ("encrypted_value123XYZ", cookie_name->Value()); - EXPECT_EQ("something456ABC", cookie_other->Value()); - DestroyStore(); - STLDeleteElements(&cookies_); - - // Examine the real record to make sure plaintext version doesn't exist. - sql::Connection db; - sql::Statement smt; - int resultcount = 0; - ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename))); - smt.Assign(db.GetCachedStatement(SQL_FROM_HERE, - "SELECT * " - "FROM cookies " - "WHERE host_key = 'foo.bar'")); - while (smt.Step()) { - resultcount++; - for (int i = 0; i < smt.ColumnCount(); i++) { - EXPECT_EQ(smt.ColumnString(i).find("value"), std::string::npos); - EXPECT_EQ(smt.ColumnString(i).find("something"), std::string::npos); - } - } - EXPECT_EQ(2, resultcount); - - // Verify that "encrypted_value" is NOT visible in the file. - contents = ReadRawDBContents(); - EXPECT_NE(0U, contents.length()); - EXPECT_EQ(contents.find("encrypted_value123XYZ"), std::string::npos); - EXPECT_EQ(contents.find("something456ABC"), std::string::npos); -} - -} // namespace net diff --git a/net/net.gyp b/net/net.gyp index e3d858c..3db83b5 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -448,13 +448,11 @@ '../testing/gtest.gyp:gtest', '../url/url.gyp:url_lib', 'net', - 'net_extras', 'net_test_support', ], 'sources': [ 'cookies/cookie_monster_perftest.cc', 'disk_cache/blockfile/disk_cache_perftest.cc', - 'extras/sqlite/sqlite_persistent_cookie_store_perftest.cc', 'proxy/proxy_resolver_perftest.cc', 'udp/udp_socket_perftest.cc', 'websockets/websocket_frame_perftest.cc', diff --git a/net/net.gypi b/net/net.gypi index c2148c0..e15717e 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -1272,8 +1272,6 @@ 'extras/sqlite/cookie_crypto_delegate.h', 'extras/sqlite/sqlite_channel_id_store.cc', 'extras/sqlite/sqlite_channel_id_store.h', - 'extras/sqlite/sqlite_persistent_cookie_store.cc', - 'extras/sqlite/sqlite_persistent_cookie_store.h', ], 'net_test_sources': [ 'android/keystore_unittest.cc', @@ -1390,7 +1388,6 @@ 'dns/serial_worker_unittest.cc', 'dns/single_request_host_resolver_unittest.cc', 'extras/sqlite/sqlite_channel_id_store_unittest.cc', - 'extras/sqlite/sqlite_persistent_cookie_store_unittest.cc', 'filter/filter_unittest.cc', 'filter/gzip_filter_unittest.cc', 'filter/mock_filter_context.cc', |