Commit 1860223c authored by rohitrao's avatar rohitrao Committed by Commit bot

Reland "Moves SQLitePersistentCookieStore to net/extras/sqlite."

The application of special storage policy is split out into a new class,
QuotaPolicyCookieStore, in content/browser/net.

This reverts commit ac4f4964.

TBR=avi@chromium.org
BUG=467596
TEST=No visible impact.

Review URL: https://codereview.chromium.org/1138643004

Cr-Commit-Position: refs/heads/master@{#330257}
parent ce0d1804
......@@ -34,6 +34,7 @@ source_set("browser") {
"//device/vibration",
"//google_apis",
"//net",
"//net:extras",
"//skia",
"//sql",
"//third_party/npapi",
......
// Copyright 2015 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 "content/browser/net/quota_policy_cookie_store.h"
#include <list>
#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/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/profiler/scoped_tracker.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.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 "storage/browser/quota/special_storage_policy.h"
#include "url/gurl.h"
namespace content {
QuotaPolicyCookieStore::QuotaPolicyCookieStore(
const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store,
storage::SpecialStoragePolicy* special_storage_policy)
: special_storage_policy_(special_storage_policy),
persistent_store_(cookie_store) {
}
QuotaPolicyCookieStore::~QuotaPolicyCookieStore() {
if (!special_storage_policy_.get() ||
!special_storage_policy_->HasSessionOnlyOrigins()) {
return;
}
std::list<net::SQLitePersistentCookieStore::CookieOrigin>
session_only_cookies;
for (const auto& cookie : cookies_per_origin_) {
if (cookie.second == 0) {
continue;
}
const GURL url(net::cookie_util::CookieOriginToURL(cookie.first.first,
cookie.first.second));
if (!url.is_valid() || !special_storage_policy_->IsStorageSessionOnly(url))
continue;
session_only_cookies.push_back(cookie.first);
}
persistent_store_->DeleteAllInList(session_only_cookies);
}
void QuotaPolicyCookieStore::Load(const LoadedCallback& loaded_callback) {
persistent_store_->Load(
base::Bind(&QuotaPolicyCookieStore::OnLoad, this, loaded_callback));
}
void QuotaPolicyCookieStore::LoadCookiesForKey(
const std::string& key,
const LoadedCallback& loaded_callback) {
persistent_store_->LoadCookiesForKey(
key,
base::Bind(&QuotaPolicyCookieStore::OnLoad, this, loaded_callback));
}
void QuotaPolicyCookieStore::AddCookie(const net::CanonicalCookie& cc) {
net::SQLitePersistentCookieStore::CookieOrigin origin(
cc.Domain(), cc.IsSecure());
++cookies_per_origin_[origin];
persistent_store_->AddCookie(cc);
}
void QuotaPolicyCookieStore::UpdateCookieAccessTime(
const net::CanonicalCookie& cc) {
persistent_store_->UpdateCookieAccessTime(cc);
}
void QuotaPolicyCookieStore::DeleteCookie(const net::CanonicalCookie& cc) {
net::SQLitePersistentCookieStore::CookieOrigin origin(
cc.Domain(), cc.IsSecure());
DCHECK_GE(cookies_per_origin_[origin], 1U);
--cookies_per_origin_[origin];
persistent_store_->DeleteCookie(cc);
}
void QuotaPolicyCookieStore::SetForceKeepSessionState() {
special_storage_policy_ = nullptr;
}
void QuotaPolicyCookieStore::Flush(const base::Closure& callback) {
persistent_store_->Flush(callback);
}
void QuotaPolicyCookieStore::OnLoad(
const LoadedCallback& loaded_callback,
const std::vector<net::CanonicalCookie*>& cookies) {
for (const auto& cookie : cookies) {
net::SQLitePersistentCookieStore::CookieOrigin origin(
cookie->Domain(), cookie->IsSecure());
++cookies_per_origin_[origin];
}
loaded_callback.Run(cookies);
}
CookieStoreConfig::CookieStoreConfig()
: session_cookie_mode(EPHEMERAL_SESSION_COOKIES),
crypto_delegate(nullptr) {
// Default to an in-memory cookie store.
}
CookieStoreConfig::CookieStoreConfig(
const base::FilePath& path,
SessionCookieMode session_cookie_mode,
storage::SpecialStoragePolicy* storage_policy,
net::CookieMonsterDelegate* cookie_delegate)
: path(path),
session_cookie_mode(session_cookie_mode),
storage_policy(storage_policy),
cookie_delegate(cookie_delegate),
crypto_delegate(nullptr) {
CHECK(!path.empty() || session_cookie_mode == EPHEMERAL_SESSION_COOKIES);
}
CookieStoreConfig::~CookieStoreConfig() {
}
net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
// TODO(bcwhite): Remove ScopedTracker below once crbug.com/483686 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("483686 content::CreateCookieStore"));
net::CookieMonster* cookie_monster = nullptr;
if (config.path.empty()) {
// Empty path means in-memory store.
cookie_monster = new net::CookieMonster(nullptr,
config.cookie_delegate.get());
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
config.background_task_runner;
if (!client_task_runner.get()) {
client_task_runner =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}
if (!background_task_runner.get()) {
background_task_runner =
BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
BrowserThread::GetBlockingPool()->GetSequenceToken());
}
scoped_refptr<net::SQLitePersistentCookieStore> sqlite_store(
new net::SQLitePersistentCookieStore(
config.path,
client_task_runner,
background_task_runner,
(config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES),
config.crypto_delegate));
QuotaPolicyCookieStore* persistent_store =
new QuotaPolicyCookieStore(
sqlite_store.get(),
config.storage_policy.get());
cookie_monster =
new net::CookieMonster(persistent_store, config.cookie_delegate.get());
if ((config.session_cookie_mode ==
CookieStoreConfig::PERSISTANT_SESSION_COOKIES) ||
(config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES)) {
cookie_monster->SetPersistSessionCookies(true);
}
}
return cookie_monster;
}
} // namespace content
// Copyright 2015 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 CONTENT_BROWSER_NET_QUOTA_POLICY_COOKIE_STORE_H_
#define CONTENT_BROWSER_NET_QUOTA_POLICY_COOKIE_STORE_H_
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "net/cookies/cookie_monster.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
class Task;
namespace base {
class FilePath;
class SequencedTaskRunner;
} // namespace base
namespace net {
class CanonicalCookie;
class CookieCryptoDelegate;
} // namespace net
namespace storage {
class SpecialStoragePolicy;
} // namespace storage
namespace content {
// Implements a PersistentCookieStore that deletes session cookies on
// shutdown. For documentation about the actual member functions consult the
// parent class |net::CookieMonster::PersistentCookieStore|. If provided, a
// |SpecialStoragePolicy| is consulted when the SQLite database is closed to
// decide which cookies to keep.
class CONTENT_EXPORT QuotaPolicyCookieStore
: public net::CookieMonster::PersistentCookieStore {
public:
// Wraps the passed-in |cookie_store|.
QuotaPolicyCookieStore(
const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store,
storage::SpecialStoragePolicy* special_storage_policy);
// net::CookieMonster::PersistentCookieStore:
void Load(const LoadedCallback& loaded_callback) override;
void LoadCookiesForKey(const std::string& key,
const LoadedCallback& callback) override;
void AddCookie(const net::CanonicalCookie& cc) override;
void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
void DeleteCookie(const net::CanonicalCookie& cc) override;
void SetForceKeepSessionState() override;
void Flush(const base::Closure& callback) override;
private:
typedef std::map<net::SQLitePersistentCookieStore::CookieOrigin, size_t>
CookiesPerOriginMap;
~QuotaPolicyCookieStore() override;
// Called after cookies are loaded from the database. Calls |loaded_callback|
// when done.
void OnLoad(const LoadedCallback& loaded_callback,
const std::vector<net::CanonicalCookie*>& cookies);
// Map of (domain keys(eTLD+1), is secure cookie) to number of cookies in the
// database.
CookiesPerOriginMap cookies_per_origin_;
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_refptr<net::SQLitePersistentCookieStore> persistent_store_;
DISALLOW_COPY_AND_ASSIGN(QuotaPolicyCookieStore);
};
} // namespace content
#endif // CONTENT_BROWSER_NET_QUOTA_POLICY_COOKIE_STORE_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/run_loop.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 "content/browser/net/quota_policy_cookie_store.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/test_data_directory.h"
#include "net/cookies/cookie_util.h"
#include "net/ssl/ssl_client_cert_type.h"
#include "net/test/cert_test_util.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const base::FilePath::CharType kTestCookiesFilename[] =
FILE_PATH_LITERAL("Cookies");
}
namespace content {
namespace {
typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector;
class QuotaPolicyCookieStoreTest : public testing::Test {
public:
QuotaPolicyCookieStoreTest()
: pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")),
loaded_event_(false, false),
destroy_event_(false, false) {
}
void OnLoaded(const CanonicalCookieVector& cookies) {
cookies_ = cookies;
loaded_event_.Signal();
}
void Load(CanonicalCookieVector* cookies) {
EXPECT_FALSE(loaded_event_.IsSignaled());
store_->Load(base::Bind(&QuotaPolicyCookieStoreTest::OnLoaded,
base::Unretained(this)));
loaded_event_.Wait();
*cookies = cookies_;
}
void ReleaseStore() {
EXPECT_TRUE(background_task_runner()->RunsTasksOnCurrentThread());
store_ = nullptr;
destroy_event_.Signal();
}
void DestroyStoreOnBackgroundThread() {
background_task_runner()->PostTask(
FROM_HERE, base::Bind(&QuotaPolicyCookieStoreTest::ReleaseStore,
base::Unretained(this)));
destroy_event_.Wait();
DestroyStore();
}
protected:
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 CreateAndLoad(storage::SpecialStoragePolicy* storage_policy,
CanonicalCookieVector* cookies) {
scoped_refptr<net::SQLitePersistentCookieStore> sqlite_store(
new net::SQLitePersistentCookieStore(
temp_dir_.path().Append(kTestCookiesFilename),
client_task_runner(),
background_task_runner(),
true, nullptr));
store_ = new QuotaPolicyCookieStore(sqlite_store.get(), storage_policy);
Load(cookies);
}
// 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(
net::CanonicalCookie(
GURL(), name, value, domain, path, creation, creation, creation,
false, false, false, net::COOKIE_PRIORITY_DEFAULT));
}
void DestroyStore() {
store_ = nullptr;
// Ensure that |store_|'s destructor has run by shutting down the pool and
// then forcing the pool to be destructed. This will ensure that all the
// tasks that block pool shutdown (e.g. |store_|'s cleanup) have run before
// yielding control.
pool_owner_->pool()->FlushForTesting();
pool_owner_->pool()->Shutdown();
pool_owner_.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool"));
}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
void TearDown() override {
DestroyStore();
pool_owner_->pool()->Shutdown();
}
TestBrowserThreadBundle bundle_;
scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
base::WaitableEvent loaded_event_;
base::WaitableEvent destroy_event_;
base::ScopedTempDir temp_dir_;
scoped_refptr<QuotaPolicyCookieStore> store_;
CanonicalCookieVector cookies_;
};
// Test if data is stored as expected in the QuotaPolicy database.
TEST_F(QuotaPolicyCookieStoreTest, TestPersistence) {
CanonicalCookieVector cookies;
CreateAndLoad(nullptr, &cookies);
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
AddCookie("A", "B", "foo.com", "/", t);
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "persistent.com", "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
// making sure it loads successfully. This ensures that all pending commits
// are made to the store before allowing it to be closed.
DestroyStore();
// Reload and test for persistence.
STLDeleteElements(&cookies);
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(2U, cookies.size());
bool found_foo_cookie = false;
bool found_persistent_cookie = false;
for (const auto& cookie : cookies) {
if (cookie->Domain() == "foo.com")
found_foo_cookie = true;
else if (cookie->Domain() == "persistent.com")
found_persistent_cookie = true;
}
EXPECT_TRUE(found_foo_cookie);
EXPECT_TRUE(found_persistent_cookie);
// Now delete the cookies and check persistence again.
store_->DeleteCookie(*cookies[0]);
store_->DeleteCookie(*cookies[1]);
DestroyStore();
// Reload and check if the cookies have been removed.
STLDeleteElements(&cookies);
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(0U, cookies.size());
STLDeleteElements(&cookies);
}
// Test if data is stored as expected in the QuotaPolicy database.
TEST_F(QuotaPolicyCookieStoreTest, TestPolicy) {
CanonicalCookieVector cookies;
CreateAndLoad(nullptr, &cookies);
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
AddCookie("A", "B", "foo.com", "/", t);
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "persistent.com", "/", t);
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "nonpersistent.com", "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
// making sure it loads successfully. This ensures that all pending commits
// are made to the store before allowing it to be closed.
DestroyStore();
// Specify storage policy that makes "nonpersistent.com" session only.
scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
new content::MockSpecialStoragePolicy();
storage_policy->AddSessionOnly(
net::cookie_util::CookieOriginToURL("nonpersistent.com", false));
// Reload and test for persistence.
STLDeleteElements(&cookies);
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(3U, cookies.size());
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "nonpersistent.com", "/second", t);
// Now close the store, and "nonpersistent.com" should be deleted according to
// policy.
DestroyStore();
STLDeleteElements(&cookies);
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(2U, cookies.size());
for (const auto& cookie : cookies) {
EXPECT_NE("nonpersistent.com", cookie->Domain());
}
STLDeleteElements(&cookies);
}
TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
CanonicalCookieVector cookies;
CreateAndLoad(nullptr, &cookies);
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
AddCookie("A", "B", "foo.com", "/", t);
// Recreate |store_| with a storage policy that makes "nonpersistent.com"
// session only, but then instruct the store to forcibly keep all cookies.
DestroyStore();
scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
new content::MockSpecialStoragePolicy();
storage_policy->AddSessionOnly(
net::cookie_util::CookieOriginToURL("nonpersistent.com", false));
// Reload and test for persistence
STLDeleteElements(&cookies);
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(1U, cookies.size());
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "persistent.com", "/", t);
t += base::TimeDelta::FromInternalValue(10);
AddCookie("A", "B", "nonpersistent.com", "/", t);
// Now close the store, but the "nonpersistent.com" cookie should not be
// deleted.
store_->SetForceKeepSessionState();
DestroyStore();
STLDeleteElements(&cookies);
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(3U, cookies.size());
STLDeleteElements(&cookies);
}
// Tests that the special storage policy is properly applied even when the store
// is destroyed on a background thread.
TEST_F(QuotaPolicyCookieStoreTest, TestDestroyOnBackgroundThread) {
// Specify storage policy that makes "nonpersistent.com" session only.
scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
new content::MockSpecialStoragePolicy();
storage_policy->AddSessionOnly(
net::cookie_util::CookieOriginToURL("nonpersistent.com", false));
CanonicalCookieVector cookies;
CreateAndLoad(storage_policy.get(), &cookies);
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
AddCookie("A", "B", "nonpersistent.com", "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
// making sure it loads successfully. This ensures that all pending commits
// are made to the store before allowing it to be closed.
DestroyStoreOnBackgroundThread();
// Reload and test for persistence.
STLDeleteElements(&cookies);
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(0U, cookies.size());
STLDeleteElements(&cookies);
}
} // namespace
} // namespace content
......@@ -12,6 +12,7 @@
'../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
'../google_apis/google_apis.gyp:google_apis',
'../net/net.gyp:net',
'../net/net.gyp:net_extras',
'../skia/skia.gyp:skia',
'../sql/sql.gyp:sql',
'../third_party/re2/re2.gyp:re2',
......@@ -1028,8 +1029,8 @@
'browser/navigator_connect/navigator_connect_service_worker_service_factory.h',
'browser/net/browser_online_state_observer.cc',
'browser/net/browser_online_state_observer.h',
'browser/net/sqlite_persistent_cookie_store.cc',
'browser/net/sqlite_persistent_cookie_store.h',
'browser/net/quota_policy_cookie_store.cc',
'browser/net/quota_policy_cookie_store.h',
'browser/net/view_blob_internals_job_factory.cc',
'browser/net/view_blob_internals_job_factory.h',
'browser/net/view_http_cache_job_factory.cc',
......
......@@ -480,7 +480,7 @@
'browser/media/media_internals_unittest.cc',
'browser/media/midi_host_unittest.cc',
'browser/media/webrtc_identity_store_unittest.cc',
'browser/net/sqlite_persistent_cookie_store_unittest.cc',
'browser/net/quota_policy_cookie_store_unittest.cc',
'browser/notification_service_impl_unittest.cc',
'browser/notifications/notification_database_data_unittest.cc',
'browser/notifications/notification_database_unittest.cc',
......@@ -979,6 +979,7 @@
'../device/battery/battery.gyp:device_battery',
'../device/battery/battery.gyp:device_battery_mojo_bindings',
'../mojo/mojo_base.gyp:mojo_environment_chromium',
'../net/net.gyp:net_extras',
'../net/net.gyp:net_test_support',
'../skia/skia.gyp:skia',
'../sql/sql.gyp:sql',
......@@ -1253,7 +1254,6 @@
'..',
],
'sources': [
'browser/net/sqlite_persistent_cookie_store_perftest.cc',
'browser/renderer_host/input/input_router_impl_perftest.cc',
'common/cc_messages_perftest.cc',
'common/discardable_shared_memory_heap_perftest.cc',
......
......@@ -439,6 +439,7 @@ test("content_unittests") {
"//device/battery",
"//device/battery:mojo_bindings",
"//mojo/environment:chromium",
"//net:extras",
"//net:test_support",
"//skia",
"//sql",
......@@ -622,7 +623,6 @@ test("content_unittests") {
if (!is_mac) { # TODO(GYP) enable on Mac once it links.
test("content_perftests") {
sources = [
"../browser/net/sqlite_persistent_cookie_store_perftest.cc",
"../browser/renderer_host/input/input_router_impl_perftest.cc",
"../common/cc_messages_perftest.cc",
"../test/run_all_perftests.cc",
......
......@@ -1591,6 +1591,7 @@ 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",
]
......@@ -1603,6 +1604,7 @@ executable("net_perftests") {
"//base/test:test_support_perf",
"//testing/gtest",
"//url",
":extras",
":net",
":test_support",
]
......
......@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/net/sqlite_persistent_cookie_store.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
#include <list>
#include <map>
#include <set>
#include <utility>
#include "base/basictypes.h"
#include "base/bind.h"
......@@ -27,8 +25,6 @@
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
......@@ -38,8 +34,6 @@
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
using base::Time;
......@@ -53,7 +47,7 @@ const int kLoadDelayMilliseconds = 0;
} // namespace
namespace content {
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.
......@@ -85,15 +79,12 @@ class SQLitePersistentCookieStore::Backend
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
storage::SpecialStoragePolicy* special_storage_policy,
net::CookieCryptoDelegate* crypto_delegate)
CookieCryptoDelegate* crypto_delegate)
: path_(path),
num_pending_(0),
force_keep_session_state_(false),
initialized_(false),
corruption_detected_(false),
restore_old_session_cookies_(restore_old_session_cookies),
special_storage_policy_(special_storage_policy),
num_cookies_read_(0),
client_task_runner_(client_task_runner),
background_task_runner_(background_task_runner),
......@@ -109,19 +100,18 @@ class SQLitePersistentCookieStore::Backend
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 |cookies_per_origin_| and
// |num_cookies_read_|.
void MakeCookiesFromSQLStatement(std::vector<net::CanonicalCookie*>* cookies,
// 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 net::CanonicalCookie& cc);
void AddCookie(const CanonicalCookie& cc);
// Batch a cookie access time update.
void UpdateCookieAccessTime(const net::CanonicalCookie& cc);
void UpdateCookieAccessTime(const CanonicalCookie& cc);
// Batch a cookie deletion.
void DeleteCookie(const net::CanonicalCookie& cc);
void DeleteCookie(const CanonicalCookie& cc);
// Commit pending operations as soon as possible.
void Flush(const base::Closure& callback);
......@@ -130,7 +120,8 @@ class SQLitePersistentCookieStore::Backend
// before the object is destructed.
void Close();
void SetForceKeepSessionState();
// Post background delete of all cookies that match |cookies|.
void DeleteAllInList(const std::list<CookieOrigin>& cookies);
private:
friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>;
......@@ -138,9 +129,10 @@ class SQLitePersistentCookieStore::Backend
// You should call Close() before destructing this object.
~Backend() {
DCHECK(!db_.get()) << "Close should have already been called.";
DCHECK(num_pending_ == 0 && pending_.empty());
DCHECK_EQ(0u, num_pending_);
DCHECK(pending_.empty());
for (net::CanonicalCookie* cookie : cookies_) {
for (CanonicalCookie* cookie : cookies_) {
delete cookie;
}
}
......@@ -150,21 +142,21 @@ class SQLitePersistentCookieStore::Backend
class PendingOperation {
public:
typedef enum {
enum OperationType {
COOKIE_ADD,
COOKIE_UPDATEACCESS,
COOKIE_DELETE,
} OperationType;
};
PendingOperation(OperationType op, const net::CanonicalCookie& cc)
: op_(op), cc_(cc) { }
PendingOperation(OperationType op, const CanonicalCookie& cc)
: op_(op), cc_(cc) {}
OperationType op() const { return op_; }
const net::CanonicalCookie& cc() const { return cc_; }
const CanonicalCookie& cc() const { return cc_; }
private:
OperationType op_;
net::CanonicalCookie cc_;
CanonicalCookie cc_;
};
private:
......@@ -215,7 +207,7 @@ class SQLitePersistentCookieStore::Backend
// Batch a cookie operation (add or delete)
void BatchOperation(PendingOperation::OperationType op,
const net::CanonicalCookie& cc);
const CanonicalCookie& cc);
// Commit our pending operations to the database.
void Commit();
// Close() executed on the background runner.
......@@ -223,7 +215,7 @@ class SQLitePersistentCookieStore::Backend
void DeleteSessionCookiesOnStartup();
void DeleteSessionCookiesOnShutdown();
void BackgroundDeleteAllInList(const std::list<CookieOrigin>& cookies);
void DatabaseErrorCallback(int error, sql::Statement* stmt);
void KillDatabase();
......@@ -238,16 +230,14 @@ class SQLitePersistentCookieStore::Backend
void FinishedLoadingCookies(const LoadedCallback& loaded_callback,
bool success);
base::FilePath path_;
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_;
// True if the persistent store should skip delete on exit rules.
bool force_keep_session_state_;
// Guard |cookies_|, |pending_|, |num_pending_|, |force_keep_session_state_|
// Guard |cookies_|, |pending_|, |num_pending_|.
base::Lock lock_;
// Temporary buffer for cookies loaded from DB. Accumulates cookies to reduce
......@@ -255,16 +245,10 @@ class SQLitePersistentCookieStore::Backend
// 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<net::CanonicalCookie*> cookies_;
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_;
// Map of (domain keys(eTLD+1), is secure cookie) to number of cookies in the
// database.
typedef std::pair<std::string, bool> CookieOrigin;
typedef std::map<CookieOrigin, int> CookiesPerOriginMap;
CookiesPerOriginMap cookies_per_origin_;
std::map<std::string, std::set<std::string>> keys_to_load_;
// Indicates if DB has been initialized.
bool initialized_;
......@@ -275,9 +259,6 @@ class SQLitePersistentCookieStore::Backend
// If false, we should filter out session cookies when reading the DB.
bool restore_old_session_cookies_;
// Policy defining what data is deleted on shutdown.
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
// The cumulative time spent loading the cookies on the background runner.
// Incremented and reported from the background runner.
base::TimeDelta cookie_load_duration_;
......@@ -304,7 +285,7 @@ class SQLitePersistentCookieStore::Backend
// cookies stored persistently).
//
// Not owned.
net::CookieCryptoDelegate* crypto_;
CookieCryptoDelegate* crypto_;
DISALLOW_COPY_AND_ASSIGN(Backend);
};
......@@ -353,13 +334,13 @@ enum DBCookiePriority {
kCookiePriorityHigh = 2,
};
DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) {
DBCookiePriority CookiePriorityToDBCookiePriority(CookiePriority value) {
switch (value) {
case net::COOKIE_PRIORITY_LOW:
case COOKIE_PRIORITY_LOW:
return kCookiePriorityLow;
case net::COOKIE_PRIORITY_MEDIUM:
case COOKIE_PRIORITY_MEDIUM:
return kCookiePriorityMedium;
case net::COOKIE_PRIORITY_HIGH:
case COOKIE_PRIORITY_HIGH:
return kCookiePriorityHigh;
}
......@@ -367,18 +348,18 @@ DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) {
return kCookiePriorityMedium;
}
net::CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
switch (value) {
case kCookiePriorityLow:
return net::COOKIE_PRIORITY_LOW;
return COOKIE_PRIORITY_LOW;
case kCookiePriorityMedium:
return net::COOKIE_PRIORITY_MEDIUM;
return COOKIE_PRIORITY_MEDIUM;
case kCookiePriorityHigh:
return net::COOKIE_PRIORITY_HIGH;
return COOKIE_PRIORITY_HIGH;
}
NOTREACHED();
return net::COOKIE_PRIORITY_DEFAULT;
return COOKIE_PRIORITY_DEFAULT;
}
// Increments a specified TimeDelta by the duration between this object's
......@@ -387,10 +368,8 @@ net::CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
// The shortest lived instances have no impact.
class IncrementTimeDelta {
public:
explicit IncrementTimeDelta(base::TimeDelta* delta) :
delta_(delta),
original_value_(*delta),
start_(base::Time::Now()) {}
explicit IncrementTimeDelta(base::TimeDelta* delta)
: delta_(delta), original_value_(*delta), start_(base::Time::Now()) {}
~IncrementTimeDelta() {
*delta_ = original_value_ + base::Time::Now() - start_;
......@@ -425,7 +404,7 @@ bool InitTable(sql::Connection* db) {
"priority INTEGER NOT NULL DEFAULT %d,"
"encrypted_value BLOB DEFAULT '',"
"firstpartyonly INTEGER NOT NULL DEFAULT 0)",
CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT)));
CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT)));
if (!db->Execute(stmt.c_str()))
return false;
......@@ -451,8 +430,8 @@ bool InitTable(sql::Connection* db) {
void SQLitePersistentCookieStore::Backend::Load(
const LoadedCallback& loaded_callback) {
PostBackgroundTask(FROM_HERE, base::Bind(
&Backend::LoadAndNotifyInBackground, this,
PostBackgroundTask(FROM_HERE,
base::Bind(&Backend::LoadAndNotifyInBackground, this,
loaded_callback, base::Time::Now()));
}
......@@ -467,25 +446,25 @@ void SQLitePersistentCookieStore::Backend::LoadCookiesForKey(
total_priority_requests_++;
}
PostBackgroundTask(FROM_HERE, base::Bind(
&Backend::LoadKeyAndNotifyInBackground,
this, key, loaded_callback, base::Time::Now()));
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) {
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",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoadDBQueueWait",
base::Time::Now() - posted_at,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1), 50);
if (!InitializeDatabase()) {
PostClientTask(FROM_HERE, base::Bind(
&Backend::CompleteLoadInForeground, this, loaded_callback, false));
PostClientTask(FROM_HERE, base::Bind(&Backend::CompleteLoadInForeground,
this, loaded_callback, false));
} else {
ChainLoadCookies(loaded_callback);
}
......@@ -498,16 +477,15 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground(
DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
IncrementTimeDelta increment(&cookie_load_duration_);
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.TimeKeyLoadDBQueueWait",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadDBQueueWait",
base::Time::Now() - posted_at,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
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);
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);
......@@ -516,7 +494,9 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground(
}
}
PostClientTask(FROM_HERE, base::Bind(
PostClientTask(
FROM_HERE,
base::Bind(
&SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground,
this, loaded_callback, success, posted_at));
}
......@@ -524,14 +504,13 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground(
void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground(
const LoadedCallback& loaded_callback,
bool load_success,
const::Time& requested_at) {
const ::Time& requested_at) {
DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.TimeKeyLoadTotalWait",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadTotalWait",
base::Time::Now() - requested_at,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1), 50);
Notify(loaded_callback, load_success);
......@@ -543,41 +522,39 @@ void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground(
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);
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));
PostBackgroundTask(
FROM_HERE,
base::Bind(
&SQLitePersistentCookieStore::Backend::ReportMetricsInBackground,
this));
{
base::AutoLock locked(metrics_lock_);
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.PriorityBlockingTime",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.PriorityBlockingTime",
priority_wait_duration_,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1), 50);
UMA_HISTOGRAM_COUNTS_100(
"Cookie.PriorityLoadCount",
UMA_HISTOGRAM_COUNTS_100("Cookie.PriorityLoadCount",
total_priority_requests_);
UMA_HISTOGRAM_COUNTS_10000(
"Cookie.NumberOfLoadedCookies",
UMA_HISTOGRAM_COUNTS_10000("Cookie.NumberOfLoadedCookies",
num_cookies_read_);
}
}
void SQLitePersistentCookieStore::Backend::CompleteLoadInForeground(
const LoadedCallback& loaded_callback, bool load_success) {
const LoadedCallback& loaded_callback,
bool load_success) {
Notify(loaded_callback, load_success);
if (load_success)
......@@ -589,7 +566,7 @@ void SQLitePersistentCookieStore::Backend::Notify(
bool load_success) {
DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
std::vector<net::CanonicalCookie*> cookies;
std::vector<CanonicalCookie*> cookies;
{
base::AutoLock locked(lock_);
cookies.swap(cookies_);
......@@ -616,7 +593,7 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
int64 db_size = 0;
if (base::GetFileSize(path_, &db_size))
UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 );
UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024);
db_.reset(new sql::Connection);
db_->set_histogram_tag("Cookie");
......@@ -644,17 +621,16 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
return false;
}
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.TimeInitializeDB",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeInitializeDB",
base::Time::Now() - start,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
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"));
sql::Statement smt(
db_->GetUniqueStatement("SELECT DISTINCT host_key FROM cookies"));
if (!smt.is_valid()) {
if (corruption_detected_)
......@@ -668,36 +644,31 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
while (smt.Step())
host_keys.push_back(smt.ColumnString(0));
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.TimeLoadDomains",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoadDomains",
base::Time::Now() - start,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
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 =
net::registry_controlled_domains::GetDomainAndRegistry(
domain,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
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",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeParseDomains",
base::Time::Now() - start_parse,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1), 50);
UMA_HISTOGRAM_CUSTOM_TIMES(
"Cookie.TimeInitializeDomainMap",
UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeInitializeDomainMap",
base::Time::Now() - start,
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
50);
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(1), 50);
initialized_ = true;
......@@ -718,8 +689,8 @@ void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
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();
std::map<std::string, std::set<std::string>>::iterator it =
keys_to_load_.begin();
load_success = LoadCookiesForDomains(it->second);
keys_to_load_.erase(it);
}
......@@ -767,7 +738,7 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
return false;
}
std::vector<net::CanonicalCookie*> cookies;
std::vector<CanonicalCookie*> cookies;
std::set<std::string>::const_iterator it = domains.begin();
for (; it != domains.end(); ++it) {
smt.BindString(0, *it);
......@@ -782,7 +753,7 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
}
void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
std::vector<net::CanonicalCookie*>* cookies,
std::vector<CanonicalCookie*>* cookies,
sql::Statement* statement) {
sql::Statement& smt = *statement;
while (smt.Step()) {
......@@ -794,7 +765,7 @@ void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
DCHECK(encrypted_value.empty());
value = smt.ColumnString(3);
}
scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie(
scoped_ptr<CanonicalCookie> cc(new CanonicalCookie(
// The "source" URL is not used with persisted cookies.
GURL(), // Source
smt.ColumnString(2), // name
......@@ -811,7 +782,6 @@ void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
static_cast<DBCookiePriority>(smt.ColumnInt(13))))); // priority
DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
<< L"CreationDate too recent";
cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++;
cookies->push_back(cc.release());
++num_cookies_read_;
}
......@@ -819,8 +789,8 @@ void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
// Version check.
if (!meta_table_.Init(
db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
if (!meta_table_.Init(db_.get(), kCurrentVersionNumber,
kCompatibleVersionNumber)) {
return false;
}
......@@ -834,7 +804,8 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return false;
if (!db_->Execute("ALTER TABLE cookies ADD COLUMN last_access_utc "
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.";
......@@ -886,9 +857,11 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return false;
if (!db_->Execute("ALTER TABLE cookies "
if (!db_->Execute(
"ALTER TABLE cookies "
"ADD COLUMN has_expires INTEGER DEFAULT 1") ||
!db_->Execute("ALTER TABLE cookies "
!db_->Execute(
"ALTER TABLE cookies "
"ADD COLUMN persistent INTEGER DEFAULT 1")) {
LOG(WARNING) << "Unable to update cookie database to version 5.";
return false;
......@@ -910,7 +883,7 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
// 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(net::COOKIE_PRIORITY_DEFAULT)));
CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT)));
if (!db_->Execute(stmt.c_str())) {
LOG(WARNING) << "Unable to update cookie database to version 6.";
return false;
......@@ -930,7 +903,8 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
if (!transaction.Begin())
return false;
// Alter the table to add empty "encrypted value" column.
if (!db_->Execute("ALTER TABLE cookies "
if (!db_->Execute(
"ALTER TABLE cookies "
"ADD COLUMN encrypted_value BLOB DEFAULT ''")) {
LOG(WARNING) << "Unable to update cookie database to version 7.";
return false;
......@@ -1013,10 +987,9 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
meta_table_.Reset();
db_.reset(new sql::Connection);
if (!sql::Connection::Delete(path_) ||
!db_->Open(path_) ||
!meta_table_.Init(
db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
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();
......@@ -1029,23 +1002,23 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
}
void SQLitePersistentCookieStore::Backend::AddCookie(
const net::CanonicalCookie& cc) {
const CanonicalCookie& cc) {
BatchOperation(PendingOperation::COOKIE_ADD, cc);
}
void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime(
const net::CanonicalCookie& cc) {
const CanonicalCookie& cc) {
BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc);
}
void SQLitePersistentCookieStore::Backend::DeleteCookie(
const net::CanonicalCookie& cc) {
const CanonicalCookie& cc) {
BatchOperation(PendingOperation::COOKIE_DELETE, cc);
}
void SQLitePersistentCookieStore::Backend::BatchOperation(
PendingOperation::OperationType op,
const net::CanonicalCookie& cc) {
const CanonicalCookie& cc) {
// Commit every 30 seconds.
static const int kCommitIntervalMs = 30 * 1000;
// Commit right away if we have more than 512 outstanding operations.
......@@ -1098,13 +1071,14 @@ void SQLitePersistentCookieStore::Backend::Commit() {
if (!add_smt.is_valid())
return;
sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE,
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=?"));
sql::Statement del_smt(db_->GetCachedStatement(
SQL_FROM_HERE, "DELETE FROM cookies WHERE creation_utc=?"));
if (!del_smt.is_valid())
return;
......@@ -1112,14 +1086,12 @@ void SQLitePersistentCookieStore::Backend::Commit() {
if (!transaction.Begin())
return;
for (PendingOperationsList::iterator it = ops.begin();
it != ops.end(); ++it) {
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:
cookies_per_origin_[
CookieOrigin(po->cc().Domain(), po->cc().IsSecure())]++;
add_smt.Reset(true);
add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
add_smt.BindString(1, po->cc().Domain());
......@@ -1151,8 +1123,8 @@ void SQLitePersistentCookieStore::Backend::Commit() {
case PendingOperation::COOKIE_UPDATEACCESS:
update_access_smt.Reset(true);
update_access_smt.BindInt64(0,
po->cc().LastAccessDate().ToInternalValue());
update_access_smt.BindInt64(
0, po->cc().LastAccessDate().ToInternalValue());
update_access_smt.BindInt64(1,
po->cc().CreationDate().ToInternalValue());
if (!update_access_smt.Run())
......@@ -1160,8 +1132,6 @@ void SQLitePersistentCookieStore::Backend::Commit() {
break;
case PendingOperation::COOKIE_DELETE:
cookies_per_origin_[
CookieOrigin(po->cc().Domain(), po->cc().IsSecure())]--;
del_smt.Reset(true);
del_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
if (!del_smt.Run())
......@@ -1209,59 +1179,10 @@ void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() {
// Commit any pending operations
Commit();
if (!force_keep_session_state_ && special_storage_policy_.get() &&
special_storage_policy_->HasSessionOnlyOrigins()) {
DeleteSessionCookiesOnShutdown();
}
meta_table_.Reset();
db_.reset();
}
void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnShutdown() {
DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
if (!db_)
return;
if (!special_storage_policy_.get())
return;
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 (CookiesPerOriginMap::iterator it = cookies_per_origin_.begin();
it != cookies_per_origin_.end(); ++it) {
if (it->second <= 0) {
DCHECK_EQ(0, it->second);
continue;
}
const GURL url(net::cookie_util::CookieOriginToURL(it->first.first,
it->first.second));
if (!url.is_valid() || !special_storage_policy_->IsStorageSessionOnly(url))
continue;
del_smt.Reset(true);
del_smt.BindString(0, it->first.first);
del_smt.BindInt(1, it->first.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::DatabaseErrorCallback(
int error,
sql::Statement* stmt) {
......@@ -1298,9 +1219,19 @@ void SQLitePersistentCookieStore::Backend::KillDatabase() {
}
}
void SQLitePersistentCookieStore::Backend::SetForceKeepSessionState() {
base::AutoLock locked(lock_);
force_keep_session_state_ = true;
void SQLitePersistentCookieStore::Backend::DeleteAllInList(
const std::list<CookieOrigin>& cookies) {
if (cookies.empty())
return;
if (background_task_runner_->RunsTasksOnCurrentThread()) {
BackgroundDeleteAllInList(cookies);
} else {
// Perform deletion on background task runner.
PostBackgroundTask(
FROM_HERE,
base::Bind(&Backend::BackgroundDeleteAllInList, this, cookies));
}
}
void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
......@@ -1315,8 +1246,50 @@ void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
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) {
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_.";
......@@ -1324,7 +1297,8 @@ void SQLitePersistentCookieStore::Backend::PostBackgroundTask(
}
void SQLitePersistentCookieStore::Backend::PostClientTask(
const tracked_objects::Location& origin, const base::Closure& task) {
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_.";
......@@ -1343,16 +1317,19 @@ SQLitePersistentCookieStore::SQLitePersistentCookieStore(
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
storage::SpecialStoragePolicy* special_storage_policy,
net::CookieCryptoDelegate* crypto_delegate)
CookieCryptoDelegate* crypto_delegate)
: backend_(new Backend(path,
client_task_runner,
background_task_runner,
restore_old_session_cookies,
special_storage_policy,
crypto_delegate)) {
}
void SQLitePersistentCookieStore::DeleteAllInList(
const std::list<CookieOrigin>& cookies) {
backend_->DeleteAllInList(cookies);
}
void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
backend_->Load(loaded_callback);
}
......@@ -1363,21 +1340,21 @@ void SQLitePersistentCookieStore::LoadCookiesForKey(
backend_->LoadCookiesForKey(key, loaded_callback);
}
void SQLitePersistentCookieStore::AddCookie(const net::CanonicalCookie& cc) {
void SQLitePersistentCookieStore::AddCookie(const CanonicalCookie& cc) {
backend_->AddCookie(cc);
}
void SQLitePersistentCookieStore::UpdateCookieAccessTime(
const net::CanonicalCookie& cc) {
const CanonicalCookie& cc) {
backend_->UpdateCookieAccessTime(cc);
}
void SQLitePersistentCookieStore::DeleteCookie(const net::CanonicalCookie& cc) {
void SQLitePersistentCookieStore::DeleteCookie(const CanonicalCookie& cc) {
backend_->DeleteCookie(cc);
}
void SQLitePersistentCookieStore::SetForceKeepSessionState() {
backend_->SetForceKeepSessionState();
// This store never discards session-only cookies, so this call has no effect.
}
void SQLitePersistentCookieStore::Flush(const base::Closure& callback) {
......@@ -1390,76 +1367,4 @@ SQLitePersistentCookieStore::~SQLitePersistentCookieStore() {
// a reference if the background runner has not run Close() yet.
}
CookieStoreConfig::CookieStoreConfig()
: session_cookie_mode(EPHEMERAL_SESSION_COOKIES),
crypto_delegate(NULL) {
// Default to an in-memory cookie store.
}
CookieStoreConfig::CookieStoreConfig(
const base::FilePath& path,
SessionCookieMode session_cookie_mode,
storage::SpecialStoragePolicy* storage_policy,
net::CookieMonsterDelegate* cookie_delegate)
: path(path),
session_cookie_mode(session_cookie_mode),
storage_policy(storage_policy),
cookie_delegate(cookie_delegate),
crypto_delegate(NULL) {
CHECK(!path.empty() || session_cookie_mode == EPHEMERAL_SESSION_COOKIES);
}
CookieStoreConfig::~CookieStoreConfig() {
}
net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
// TODO(bcwhite): Remove ScopedTracker below once crbug.com/483686 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("483686 content::CreateCookieStore"));
net::CookieMonster* cookie_monster = NULL;
if (config.path.empty()) {
// Empty path means in-memory store.
cookie_monster = new net::CookieMonster(NULL, config.cookie_delegate.get());
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
config.background_task_runner;
if (!client_task_runner.get()) {
client_task_runner =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}
if (!background_task_runner.get()) {
background_task_runner =
BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
BrowserThread::GetBlockingPool()->GetSequenceToken());
}
SQLitePersistentCookieStore* persistent_store =
new SQLitePersistentCookieStore(
config.path,
client_task_runner,
background_task_runner,
(config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES),
config.storage_policy.get(),
config.crypto_delegate);
cookie_monster =
new net::CookieMonster(persistent_store, config.cookie_delegate.get());
if ((config.session_cookie_mode ==
CookieStoreConfig::PERSISTANT_SESSION_COOKIES) ||
(config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES)) {
cookie_monster->SetPersistSessionCookies(true);
}
}
return cookie_monster;
}
} // namespace content
} // namespace net
......@@ -2,18 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A sqlite implementation of a cookie monster persistent store.
#ifndef CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
#define CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
#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/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "net/cookies/cookie_monster.h"
class Task;
......@@ -21,27 +19,22 @@ class Task;
namespace base {
class FilePath;
class SequencedTaskRunner;
}
} // namespace base
namespace net {
class CanonicalCookie;
class CookieCryptoDelegate;
}
namespace storage {
class SpecialStoragePolicy;
}
namespace content {
// Implements the PersistentCookieStore interface in terms of a SQLite database.
// For documentation about the actual member functions consult the documentation
// of the parent class |net::CookieMonster::PersistentCookieStore|.
// If provided, a |SpecialStoragePolicy| is consulted when the SQLite database
// is closed to decide which cookies to keep.
class CONTENT_EXPORT SQLitePersistentCookieStore
: public net::CookieMonster::PersistentCookieStore {
// 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.
......@@ -50,23 +43,24 @@ class CONTENT_EXPORT SQLitePersistentCookieStore
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
storage::SpecialStoragePolicy* special_storage_policy,
net::CookieCryptoDelegate* crypto_delegate);
CookieCryptoDelegate* crypto_delegate);
// net::CookieMonster::PersistentCookieStore:
// 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 net::CanonicalCookie& cc) override;
void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
void DeleteCookie(const net::CanonicalCookie& cc) 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;
protected:
private:
~SQLitePersistentCookieStore() override;
private:
class Backend;
scoped_refptr<Backend> backend_;
......@@ -74,6 +68,6 @@ class CONTENT_EXPORT SQLitePersistentCookieStore
DISALLOW_COPY_AND_ASSIGN(SQLitePersistentCookieStore);
};
} // namespace content
} // namespace net
#endif // CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
#endif // NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_COOKIE_STORE_H_
......@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/net/sqlite_persistent_cookie_store.h"
#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"
......@@ -19,7 +22,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace net {
namespace {
......@@ -32,15 +35,14 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
SQLitePersistentCookieStorePerfTest()
: pool_owner_(new base::SequencedWorkerPoolOwner(1, "Background Pool")),
loaded_event_(false, false),
key_loaded_event_(false, false) {
}
key_loaded_event_(false, false) {}
void OnLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
void OnLoaded(const std::vector<CanonicalCookie*>& cookies) {
cookies_ = cookies;
loaded_event_.Signal();
}
void OnKeyLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
void OnKeyLoaded(const std::vector<CanonicalCookie*>& cookies) {
cookies_ = cookies;
key_loaded_event_.Signal();
}
......@@ -64,11 +66,9 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
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, NULL);
std::vector<net::CanonicalCookie*> cookies;
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.
......@@ -78,9 +78,9 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
GURL gurl("www" + domain_name);
for (int cookie_num = 0; cookie_num < 50; ++cookie_num) {
t += base::TimeDelta::FromInternalValue(10);
store_->AddCookie(net::CanonicalCookie(
store_->AddCookie(CanonicalCookie(
gurl, base::StringPrintf("Cookie_%d", cookie_num), "1", domain_name,
"/", t, t, t, false, false, false, net::COOKIE_PRIORITY_DEFAULT));
"/", t, t, t, false, false, false, COOKIE_PRIORITY_DEFAULT));
}
}
// Replace the store effectively destroying the current one and forcing it
......@@ -93,10 +93,8 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
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, NULL);
temp_dir_.path().Append(cookie_filename), client_task_runner(),
background_task_runner(), false, NULL);
}
void TearDown() override {
......@@ -105,10 +103,11 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
}
protected:
base::MessageLoop main_loop_;
scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
base::WaitableEvent loaded_event_;
base::WaitableEvent key_loaded_event_;
std::vector<net::CanonicalCookie*> cookies_;
std::vector<CanonicalCookie*> cookies_;
base::ScopedTempDir temp_dir_;
scoped_refptr<SQLitePersistentCookieStore> store_;
};
......@@ -119,7 +118,8 @@ TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadForKeyPerformance) {
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,
store_->LoadCookiesForKey(
domain_name,
base::Bind(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded,
base::Unretained(this)));
key_loaded_event_.Wait();
......@@ -138,4 +138,4 @@ TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadPerformance) {
ASSERT_EQ(15000U, cookies_.size());
}
} // namespace content
} // namespace net
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/net/sqlite_persistent_cookie_store.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
#include <map>
#include <set>
......@@ -11,15 +11,14 @@
#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/message_loop/message_loop.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 "content/public/browser/cookie_store_factory.h"
#include "crypto/encryptor.h"
#include "crypto/symmetric_key.h"
#include "net/cookies/canonical_cookie.h"
......@@ -31,13 +30,13 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace net {
namespace {
const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
class CookieCryptor : public net::CookieCryptoDelegate {
class CookieCryptor : public CookieCryptoDelegate {
public:
CookieCryptor();
bool EncryptString(const std::string& plaintext,
......@@ -50,9 +49,13 @@ class CookieCryptor : public net::CookieCryptoDelegate {
crypto::Encryptor encryptor_;
};
CookieCryptor::CookieCryptor() : key_(
crypto::SymmetricKey::DeriveKeyFromPassword(
crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)) {
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);
}
......@@ -69,7 +72,7 @@ bool CookieCryptor::DecryptString(const std::string& ciphertext,
} // namespace
typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector;
typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
class SQLitePersistentCookieStoreTest : public testing::Test {
public:
......@@ -77,8 +80,7 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
: pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")),
loaded_event_(false, false),
key_loaded_event_(false, false),
db_thread_event_(false, false) {
}
db_thread_event_(false, false) {}
void OnLoaded(const CanonicalCookieVector& cookies) {
cookies_ = cookies;
......@@ -100,8 +102,8 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
void Flush() {
base::WaitableEvent event(false, false);
store_->Flush(base::Bind(&base::WaitableEvent::Signal,
base::Unretained(&event)));
store_->Flush(
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
event.Wait();
}
......@@ -116,7 +118,7 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
}
void DestroyStore() {
store_ = NULL;
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();
......@@ -132,11 +134,8 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
cookie_crypto_delegate_.reset(new CookieCryptor());
store_ = new SQLitePersistentCookieStore(
temp_dir_.path().Append(kCookieFilename),
client_task_runner(),
background_task_runner(),
restore_old_session_cookies,
NULL,
temp_dir_.path().Append(kCookieFilename), client_task_runner(),
background_task_runner(), restore_old_session_cookies,
cookie_crypto_delegate_.get());
Load(cookies);
}
......@@ -149,9 +148,7 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
// 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();
}
void WaitOnDBEvent() { db_thread_event_.Wait(); }
// Adds a persistent cookie to store_.
void AddCookie(const std::string& name,
......@@ -159,9 +156,9 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
const std::string& domain,
const std::string& path,
const base::Time& creation) {
store_->AddCookie(net::CanonicalCookie(
GURL(), name, value, domain, path, creation, creation, creation, false,
false, false, net::COOKIE_PRIORITY_DEFAULT));
store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path,
creation, creation, creation, false,
false, false, COOKIE_PRIORITY_DEFAULT));
}
void AddCookieWithExpiration(const std::string& name,
......@@ -170,9 +167,9 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
const std::string& path,
const base::Time& creation,
const base::Time& expiration) {
store_->AddCookie(net::CanonicalCookie(
GURL(), name, value, domain, path, creation, expiration, creation,
false, false, false, net::COOKIE_PRIORITY_DEFAULT));
store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path,
creation, expiration, creation, false,
false, false, COOKIE_PRIORITY_DEFAULT));
}
std::string ReadRawDBContents() {
......@@ -191,7 +188,6 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
}
protected:
base::MessageLoop main_loop_;
scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
base::WaitableEvent loaded_event_;
base::WaitableEvent key_loaded_event_;
......@@ -199,7 +195,7 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
CanonicalCookieVector cookies_;
base::ScopedTempDir temp_dir_;
scoped_refptr<SQLitePersistentCookieStore> store_;
scoped_ptr<net::CookieCryptoDelegate> cookie_crypto_delegate_;
scoped_ptr<CookieCryptoDelegate> cookie_crypto_delegate_;
};
TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
......@@ -297,24 +293,21 @@ TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) {
// 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, NULL, NULL);
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,
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)));
store_->Flush(
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
// Now the DB-thread queue contains:
// (active:)
......@@ -333,10 +326,8 @@ TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) {
// 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, NULL, NULL);
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();
......@@ -359,25 +350,21 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
DestroyStore();
store_ = new SQLitePersistentCookieStore(
temp_dir_.path().Append(kCookieFilename),
client_task_runner(),
background_task_runner(),
false, NULL, NULL);
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,
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,
store_->LoadCookiesForKey(
"aaa.com", base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded,
base::Unretained(this)));
background_task_runner()->PostTask(
FROM_HERE,
base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
FROM_HERE, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
base::Unretained(this)));
// Now the DB-thread queue contains:
......@@ -392,8 +379,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
ASSERT_EQ(loaded_event_.IsSignaled(), false);
std::set<std::string> cookies_loaded;
for (CanonicalCookieVector::const_iterator it = cookies_.begin();
it != cookies_.end();
++it) {
it != cookies_.end(); ++it) {
cookies_loaded.insert((*it)->Domain().c_str());
}
STLDeleteElements(&cookies_);
......@@ -405,13 +391,11 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
db_thread_event_.Signal();
loaded_event_.Wait();
for (CanonicalCookieVector::const_iterator it = cookies_.begin();
it != cookies_.end();
++it) {
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("foo.bar") != cookies_loaded.end(), true);
ASSERT_EQ(cookies_loaded.find("www.bbb.com") != cookies_loaded.end(), true);
STLDeleteElements(&cookies_);
}
......@@ -447,10 +431,10 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
InitializeStore(false, true);
// Add a session cookie.
store_->AddCookie(net::CanonicalCookie(GURL(), "C", "D", "sessioncookie.com",
"/", base::Time::Now(), base::Time(),
store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
base::Time::Now(), base::Time(),
base::Time::Now(), false, false, false,
net::COOKIE_PRIORITY_DEFAULT));
COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
......@@ -464,7 +448,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
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(net::COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority());
ASSERT_EQ(COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority());
STLDeleteElements(&cookies);
}
......@@ -474,10 +458,10 @@ TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
InitializeStore(false, true);
// Add a session cookie.
store_->AddCookie(net::CanonicalCookie(GURL(), "C", "D", "sessioncookie.com",
"/", base::Time::Now(), base::Time(),
store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
base::Time::Now(), base::Time(),
base::Time::Now(), false, false, false,
net::COOKIE_PRIORITY_DEFAULT));
COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
......@@ -504,16 +488,16 @@ TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
static const char kPersistentName[] = "persistent";
// Add a session cookie.
store_->AddCookie(net::CanonicalCookie(
GURL(), kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(),
base::Time(), base::Time::Now(), false, false, false,
net::COOKIE_PRIORITY_DEFAULT));
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(net::CanonicalCookie(
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, net::COOKIE_PRIORITY_DEFAULT));
false, false, false, COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
......@@ -524,14 +508,13 @@ TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
CreateAndLoad(false, true, &cookies);
ASSERT_EQ(2U, cookies.size());
std::map<std::string, net::CanonicalCookie*> cookie_map;
std::map<std::string, CanonicalCookie*> cookie_map;
for (CanonicalCookieVector::const_iterator it = cookies.begin();
it != cookies.end();
++it) {
it != cookies.end(); ++it) {
cookie_map[(*it)->Name()] = *it;
}
std::map<std::string, net::CanonicalCookie*>::const_iterator 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());
......@@ -554,25 +537,25 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
InitializeStore(false, true);
// Add a low-priority persistent cookie.
store_->AddCookie(net::CanonicalCookie(
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, net::COOKIE_PRIORITY_LOW));
false, false, false, COOKIE_PRIORITY_LOW));
// Add a medium-priority persistent cookie.
store_->AddCookie(net::CanonicalCookie(
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, net::COOKIE_PRIORITY_MEDIUM));
false, false, false, COOKIE_PRIORITY_MEDIUM));
// Add a high-priority peristent cookie.
store_->AddCookie(net::CanonicalCookie(
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, net::COOKIE_PRIORITY_HIGH));
false, false, false, COOKIE_PRIORITY_HIGH));
// Force the store to write its data to the disk.
DestroyStore();
......@@ -584,26 +567,25 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
ASSERT_EQ(3U, cookies.size());
// Put the cookies into a map, by name, so we can easily find them.
std::map<std::string, net::CanonicalCookie*> cookie_map;
std::map<std::string, CanonicalCookie*> cookie_map;
for (CanonicalCookieVector::const_iterator it = cookies.begin();
it != cookies.end();
++it) {
it != cookies.end(); ++it) {
cookie_map[(*it)->Name()] = *it;
}
// Validate that each cookie has the correct priority.
std::map<std::string, net::CanonicalCookie*>::const_iterator it =
std::map<std::string, CanonicalCookie*>::const_iterator it =
cookie_map.find(kLowName);
ASSERT_TRUE(it != cookie_map.end());
EXPECT_EQ(net::COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority());
EXPECT_EQ(COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority());
it = cookie_map.find(kMediumName);
ASSERT_TRUE(it != cookie_map.end());
EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority());
EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority());
it = cookie_map.find(kHighName);
ASSERT_TRUE(it != cookie_map.end());
EXPECT_EQ(net::COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority());
EXPECT_EQ(COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority());
STLDeleteElements(&cookies);
}
......@@ -639,8 +621,8 @@ TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
STLDeleteElements(&cookies_);
CreateAndLoad(true, false, &cookies);
EXPECT_EQ(2U, cookies_.size());
net::CanonicalCookie* cookie_name = NULL;
net::CanonicalCookie* cookie_other = NULL;
CanonicalCookie* cookie_name = nullptr;
CanonicalCookie* cookie_other = nullptr;
if (cookies_[0]->Name() == "name") {
cookie_name = cookies_[0];
cookie_other = cookies_[1];
......@@ -664,7 +646,7 @@ TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
"WHERE host_key = 'foo.bar'"));
while (smt.Step()) {
resultcount++;
for (int i=0; i < smt.ColumnCount(); i++) {
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);
}
......@@ -678,4 +660,4 @@ TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
EXPECT_EQ(contents.find("something456ABC"), std::string::npos);
}
} // namespace content
} // namespace net
......@@ -451,11 +451,13 @@
'../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',
......
......@@ -1273,6 +1273,8 @@
'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',
......@@ -1389,6 +1391,7 @@
'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',
......
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