From ccf251570a3e16fa1cebc24ac8f8a3a3f05aabd1 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Sat, 28 Jun 2014 05:32:48 +0000 Subject: [PATCH] Revert 280400 "Creation of a new and improved object for the cac..." Seems to have introduced leaks: http://build.chromium.org/p/chromium.memory/builders/Linux%20ASan%20LSan%20Tests%20%281%29/builds/3527/steps/net_unittests/logs/stdio For example: Direct leak of 112 byte(s) in 1 object(s) allocated from: #0 0x5166cb in operator new(unsigned long) /usr/local/google/work/chromium/src/third_party/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:55 #1 0x16ce6be in MockDiskCache::CreateEntry(std::string const&, disk_cache::Entry**, base::Callback const&) net/http/mock_http_cache.cc:408 #2 0x37654a7 in DoCreate net/http/disk_based_cert_cache.cc:187 #3 0x37654a7 in net::DiskBasedCertCache::WriteWorker::DoLoop(int) net/http/disk_based_cert_cache.cc:158 #4 0x3768f23 in Start net/http/disk_based_cert_cache.cc:125 #5 0x3768f23 in net::DiskBasedCertCache::Set(CERTCertificateStr*, base::Callback const&) net/http/disk_based_cert_cache.cc:533 #6 0x10d0ffa in net::DiskBasedCertCache_SyncSet_Test::TestBody() net/http/disk_based_cert_cache_unittest.cc:231 #7 0x33ce728 in HandleExceptionsInMethodIfSupported testing/gtest/src/gtest.cc:2045 #8 0x33ce728 in testing::Test::Run() testing/gtest/src/gtest.cc:2061 #9 0x33d0f09 in testing::TestInfo::Run() testing/gtest/src/gtest.cc:2237 #10 0x33d1c96 in testing::TestCase::Run() testing/gtest/src/gtest.cc:2344 #11 0x33e4daa in testing::internal::UnitTestImpl::RunAllTests() testing/gtest/src/gtest.cc:4065 #12 0x33e43e0 in HandleExceptionsInMethodIfSupported testing/gtest/src/gtest.cc:2045 #13 0x33e43e0 in testing::UnitTest::Run() testing/gtest/src/gtest.cc:3697 #14 0x40a6d1c in RUN_ALL_TESTS testing/gtest/include/gtest/gtest.h:2231 #15 0x40a6d1c in base::TestSuite::Run() base/test/test_suite.cc:227 #16 0x409b4e2 in Run base/callback.h:401 #17 0x409b4e2 in base::(anonymous namespace)::LaunchUnitTestsInternal(base::Callback const&, int, bool, base::Callback const&) base/test/launcher/unit_test_launcher.cc:498 #18 0x409ae5d in base::LaunchUnitTests(int, char**, base::Callback const&) base/test/launcher/unit_test_launcher.cc:553 #19 0x2b986cc in main net/test/run_all_unittests.cc:64 #20 0x7fc4683a976c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 > Creation of a new and improved object for the caching of certificate objects on disk. > > Review URL: https://codereview.chromium.org/329733002 TBR=brandonsalmon@chromium.org Review URL: https://codereview.chromium.org/349533004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280492 0039d316-1c4b-4281-b951-d872f2087c98 --- net/http/disk_based_cert_cache.cc | 547 --------------------- net/http/disk_based_cert_cache.h | 74 --- net/http/disk_based_cert_cache_unittest.cc | 476 ------------------ net/net.gypi | 3 - 4 files changed, 1100 deletions(-) delete mode 100644 net/http/disk_based_cert_cache.cc delete mode 100644 net/http/disk_based_cert_cache.h delete mode 100644 net/http/disk_based_cert_cache_unittest.cc diff --git a/net/http/disk_based_cert_cache.cc b/net/http/disk_based_cert_cache.cc deleted file mode 100644 index 1a03557fee8cb..0000000000000 --- a/net/http/disk_based_cert_cache.cc +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2014 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/http/disk_based_cert_cache.h" - -#include - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/memory/ref_counted.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" - -namespace net { - -namespace { - -// Used to obtain a unique cache key for a certificate in the form of -// "cert:". -std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) { - SHA1HashValue fingerprint = - X509Certificate::CalculateFingerprint(cert_handle); - - return "cert:" + - base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); -} - -} // namespace - -// WriteWorkers represent pending Set jobs in the DiskBasedCertCache. Each -// certificate requested to be cached is assigned a Writeworker on a one-to-one -// basis. The same certificate should not have multiple WriteWorkers at the same -// time; instead, add a user callback to the existing WriteWorker. -class DiskBasedCertCache::WriteWorker { - public: - // |backend| is the backend to store |certificate| in, using - // |key| as the key for the disk_cache::Entry. - // |cleanup_callback| is called to clean up this ReadWorker, - // regardless of success or failure. - WriteWorker(disk_cache::Backend* backend, - const std::string& key, - X509Certificate::OSCertHandle cert_handle, - const base::Closure& cleanup_callback); - - ~WriteWorker(); - - // Writes the given certificate to the cache. On completion, will invoke all - // user callbacks. - void Start(); - - // Adds a callback to the set of callbacks to be run when this - // WriteWorker finishes processing. - void AddCallback(const SetCallback& user_callback); - - // Signals the WriteWorker to abort early. The WriteWorker will be destroyed - // upon the completion of any pending callbacks. User callbacks will be - // invoked with an empty string. - void Cancel(); - - private: - enum State { - STATE_CREATE, - STATE_CREATE_COMPLETE, - STATE_OPEN, - STATE_OPEN_COMPLETE, - STATE_WRITE, - STATE_WRITE_COMPLETE, - STATE_NONE - }; - - void OnIOComplete(int rv); - int DoLoop(int rv); - - int DoCreate(); - int DoCreateComplete(int rv); - int DoOpen(); - int DoOpenComplete(int rv); - int DoWrite(); - int DoWriteComplete(int rv); - - void Finish(int rv); - - // Invokes all of the |user_callbacks_| - void RunCallbacks(int rv); - - disk_cache::Backend* backend_; - const X509Certificate::OSCertHandle cert_handle_; - std::string key_; - bool canceled_; - - disk_cache::Entry* entry_; - State state_; - scoped_refptr buffer_; - int io_buf_len_; - - base::Closure cleanup_callback_; - std::vector user_callbacks_; - CompletionCallback io_callback_; -}; - -DiskBasedCertCache::WriteWorker::WriteWorker( - disk_cache::Backend* backend, - const std::string& key, - X509Certificate::OSCertHandle cert_handle, - const base::Closure& cleanup_callback) - : backend_(backend), - cert_handle_(cert_handle), - key_(key), - canceled_(false), - entry_(NULL), - state_(STATE_NONE), - io_buf_len_(0), - cleanup_callback_(cleanup_callback), - io_callback_( - base::Bind(&WriteWorker::OnIOComplete, base::Unretained(this))) { -} - -void DiskBasedCertCache::WriteWorker::Start() { - DCHECK_EQ(STATE_NONE, state_); - state_ = STATE_CREATE; - int rv = DoLoop(OK); - - if (rv == ERR_IO_PENDING) - return; - - Finish(rv); -} - -void DiskBasedCertCache::WriteWorker::AddCallback( - const SetCallback& user_callback) { - user_callbacks_.push_back(user_callback); -} - -void DiskBasedCertCache::WriteWorker::OnIOComplete(int rv) { - if (canceled_) { - Finish(ERR_FAILED); - return; - } - - rv = DoLoop(rv); - - if (rv == ERR_IO_PENDING) - return; - - Finish(rv); -} - -int DiskBasedCertCache::WriteWorker::DoLoop(int rv) { - do { - State next_state = state_; - state_ = STATE_NONE; - switch (next_state) { - case STATE_CREATE: - rv = DoCreate(); - break; - case STATE_CREATE_COMPLETE: - rv = DoCreateComplete(rv); - break; - case STATE_OPEN: - rv = DoOpen(); - break; - case STATE_OPEN_COMPLETE: - rv = DoOpenComplete(rv); - break; - case STATE_WRITE: - rv = DoWrite(); - break; - case STATE_WRITE_COMPLETE: - rv = DoWriteComplete(rv); - break; - case STATE_NONE: - NOTREACHED(); - break; - } - } while (rv != ERR_IO_PENDING && state_ != STATE_NONE); - - return rv; -} - -int DiskBasedCertCache::WriteWorker::DoCreate() { - state_ = STATE_CREATE_COMPLETE; - - return backend_->CreateEntry(key_, &entry_, io_callback_); -} - -int DiskBasedCertCache::WriteWorker::DoCreateComplete(int rv) { - // An error here usually signifies that the entry already exists. - // If this occurs, it is necessary to instead open the previously - // existing entry. - if (rv < 0) { - state_ = STATE_OPEN; - return OK; - } - - state_ = STATE_WRITE; - return OK; -} - -int DiskBasedCertCache::WriteWorker::DoOpen() { - state_ = STATE_OPEN_COMPLETE; - return backend_->OpenEntry(key_, &entry_, io_callback_); -} - -int DiskBasedCertCache::WriteWorker::DoOpenComplete(int rv) { - if (rv < 0) { - state_ = STATE_NONE; - return rv; - } - state_ = STATE_WRITE; - return OK; -} - -int DiskBasedCertCache::WriteWorker::DoWrite() { - std::string write_data; - bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data); - - if (!encoded) { - state_ = STATE_NONE; - return ERR_FAILED; - } - - buffer_ = new IOBuffer(write_data.size()); - io_buf_len_ = write_data.size(); - memcpy(buffer_->data(), write_data.data(), io_buf_len_); - - state_ = STATE_WRITE_COMPLETE; - - return entry_->WriteData(0 /* index */, - 0 /* offset */, - buffer_, - write_data.size(), - io_callback_, - true /* truncate */); -} - -int DiskBasedCertCache::WriteWorker::DoWriteComplete(int rv) { - state_ = STATE_NONE; - if (rv < io_buf_len_) - return ERR_FAILED; - - return OK; -} - -void DiskBasedCertCache::WriteWorker::RunCallbacks(int rv) { - std::string key; - if (rv >= 0) - key = key_; - - for (std::vector::const_iterator it = user_callbacks_.begin(); - it != user_callbacks_.end(); - ++it) { - it->Run(key); - } - user_callbacks_.clear(); -} - -void DiskBasedCertCache::WriteWorker::Finish(int rv) { - cleanup_callback_.Run(); - cleanup_callback_.Reset(); - RunCallbacks(rv); - delete this; -} - -void DiskBasedCertCache::WriteWorker::Cancel() { - canceled_ = true; -} - -DiskBasedCertCache::WriteWorker::~WriteWorker() { - if (entry_) - entry_->Close(); -} - -// ReadWorkers represent pending Get jobs in the DiskBasedCertCache. Each -// certificate requested to be retrieved from the cache is assigned a ReadWorker -// on a one-to-one basis. The same |key| should not have multiple ReadWorkers -// at the same time; instead, call AddCallback to add a user_callback_ to -// the the existing ReadWorker. -class DiskBasedCertCache::ReadWorker { - public: - // |backend| is the backend to read |certificate| from, using - // |key| as the key for the disk_cache::Entry. - // |cleanup_callback| is called to clean up this ReadWorker, - // regardless of success or failure. - ReadWorker(disk_cache::Backend* backend, - const std::string& key, - const base::Closure& cleanup_callback); - - ~ReadWorker(); - - // Reads the given certificate from the cache. On completion, will invoke all - // user callbacks. - void Start(); - - // Adds a callback to the set of callbacks to be run when this - // ReadWorker finishes processing. - void AddCallback(const GetCallback& user_callback); - - // Signals the ReadWorker to abort early. The ReadWorker will be destroyed - // upon the completion of any pending callbacks. User callbacks will be - // invoked with a NULL cert handle. - void Cancel(); - - private: - enum State { - STATE_OPEN, - STATE_OPEN_COMPLETE, - STATE_READ, - STATE_READ_COMPLETE, - STATE_NONE - }; - - void OnIOComplete(int rv); - int DoLoop(int rv); - int DoOpen(); - int DoOpenComplete(int rv); - int DoRead(); - int DoReadComplete(int rv); - void Finish(int rv); - - // Invokes all of |user_callbacks_| - void RunCallbacks(); - - disk_cache::Backend* backend_; - X509Certificate::OSCertHandle cert_handle_; - std::string key_; - bool canceled_; - - disk_cache::Entry* entry_; - - State state_; - scoped_refptr buffer_; - int io_buf_len_; - - base::Closure cleanup_callback_; - std::vector user_callbacks_; - CompletionCallback io_callback_; -}; - -DiskBasedCertCache::ReadWorker::ReadWorker( - disk_cache::Backend* backend, - const std::string& key, - const base::Closure& cleanup_callback) - : backend_(backend), - cert_handle_(NULL), - key_(key), - canceled_(false), - entry_(NULL), - state_(STATE_NONE), - io_buf_len_(0), - cleanup_callback_(cleanup_callback), - io_callback_( - base::Bind(&ReadWorker::OnIOComplete, base::Unretained(this))) { -} - -void DiskBasedCertCache::ReadWorker::Start() { - DCHECK_EQ(STATE_NONE, state_); - state_ = STATE_OPEN; - int rv = DoLoop(OK); - - if (rv == ERR_IO_PENDING) - return; - - Finish(rv); -} - -void DiskBasedCertCache::ReadWorker::AddCallback( - const GetCallback& user_callback) { - user_callbacks_.push_back(user_callback); -} - -void DiskBasedCertCache::ReadWorker::OnIOComplete(int rv) { - if (canceled_) { - Finish(ERR_FAILED); - return; - } - - rv = DoLoop(rv); - - if (rv == ERR_IO_PENDING) - return; - - Finish(rv); -} - -int DiskBasedCertCache::ReadWorker::DoLoop(int rv) { - do { - State next_state = state_; - state_ = STATE_NONE; - switch (next_state) { - case STATE_OPEN: - rv = DoOpen(); - break; - case STATE_OPEN_COMPLETE: - rv = DoOpenComplete(rv); - break; - case STATE_READ: - rv = DoRead(); - break; - case STATE_READ_COMPLETE: - rv = DoReadComplete(rv); - break; - case STATE_NONE: - NOTREACHED(); - break; - } - } while (rv != ERR_IO_PENDING && state_ != STATE_NONE); - - return rv; -} - -int DiskBasedCertCache::ReadWorker::DoOpen() { - state_ = STATE_OPEN_COMPLETE; - return backend_->OpenEntry(key_, &entry_, io_callback_); -} - -int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) { - if (rv < 0) { - state_ = STATE_NONE; - return rv; - } - state_ = STATE_READ; - return OK; -} - -int DiskBasedCertCache::ReadWorker::DoRead() { - state_ = STATE_READ_COMPLETE; - io_buf_len_ = entry_->GetDataSize(0 /* index */); - buffer_ = new IOBuffer(io_buf_len_); - return entry_->ReadData( - 0 /* index */, 0 /* offset */, buffer_, io_buf_len_, io_callback_); -} - -int DiskBasedCertCache::ReadWorker::DoReadComplete(int rv) { - state_ = STATE_NONE; - if (rv < io_buf_len_) - return ERR_FAILED; - - cert_handle_ = X509Certificate::CreateOSCertHandleFromBytes(buffer_->data(), - io_buf_len_); - if (!cert_handle_) - return ERR_FAILED; - - return OK; -} - -void DiskBasedCertCache::ReadWorker::RunCallbacks() { - for (std::vector::const_iterator it = user_callbacks_.begin(); - it != user_callbacks_.end(); - ++it) { - it->Run(cert_handle_); - } - user_callbacks_.clear(); -} - -void DiskBasedCertCache::ReadWorker::Finish(int rv) { - cleanup_callback_.Run(); - cleanup_callback_.Reset(); - RunCallbacks(); - delete this; -} - -void DiskBasedCertCache::ReadWorker::Cancel() { - canceled_ = true; -} - -DiskBasedCertCache::ReadWorker::~ReadWorker() { - if (entry_) - entry_->Close(); - if (cert_handle_) - X509Certificate::FreeOSCertHandle(cert_handle_); -} - -DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend) - : backend_(backend), weak_factory_(this) { - DCHECK(backend_); -} - -DiskBasedCertCache::~DiskBasedCertCache() { - for (WriteWorkerMap::iterator it = write_worker_map_.begin(); - it != write_worker_map_.end(); - ++it) { - it->second->Cancel(); - } - for (ReadWorkerMap::iterator it = read_worker_map_.begin(); - it != read_worker_map_.end(); - ++it) { - it->second->Cancel(); - } -} - -void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) { - DCHECK(!key.empty()); - - ReadWorkerMap::iterator it = read_worker_map_.find(key); - - if (it == read_worker_map_.end()) { - ReadWorker* worker = - new ReadWorker(backend_, - key, - base::Bind(&DiskBasedCertCache::FinishedReadOperation, - weak_factory_.GetWeakPtr(), - key)); - read_worker_map_[key] = worker; - worker->AddCallback(cb); - worker->Start(); - } else { - it->second->AddCallback(cb); - } -} - -void DiskBasedCertCache::Set(const X509Certificate::OSCertHandle cert_handle, - const SetCallback& cb) { - DCHECK(!cb.is_null()); - DCHECK(cert_handle); - std::string key = GetCacheKeyToCert(cert_handle); - - WriteWorkerMap::iterator it = write_worker_map_.find(key); - - if (it == write_worker_map_.end()) { - WriteWorker* worker = - new WriteWorker(backend_, - key, - cert_handle, - base::Bind(&DiskBasedCertCache::FinishedWriteOperation, - weak_factory_.GetWeakPtr(), - key)); - write_worker_map_[key] = worker; - worker->AddCallback(cb); - worker->Start(); - } else { - it->second->AddCallback(cb); - } -} - -void DiskBasedCertCache::FinishedWriteOperation(const std::string& key) { - write_worker_map_.erase(key); -} - -void DiskBasedCertCache::FinishedReadOperation(const std::string& key) { - read_worker_map_.erase(key); -} - -} // namespace net diff --git a/net/http/disk_based_cert_cache.h b/net/http/disk_based_cert_cache.h deleted file mode 100644 index 90757806c3993..0000000000000 --- a/net/http/disk_based_cert_cache.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 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_HTTP_DISK_BASED_CERT_CACHE_H -#define NET_HTTP_DISK_BASED_CERT_CACHE_H - -#include - -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#include "base/memory/weak_ptr.h" -#include "net/base/net_export.h" -#include "net/cert/x509_certificate.h" - -namespace disk_cache { -class Backend; -} // namespace disk_cache - -namespace net { - -// DiskBasedCertCache is used to store and retrieve X.509 certificates from the -// cache. Each individual certificate is stored separately from its certificate -// chain. No more than one copy (per certificate) will be stored on disk. -class NET_EXPORT_PRIVATE DiskBasedCertCache { - public: - typedef base::Callback - GetCallback; - typedef base::Callback SetCallback; - - // Initializes a new DiskBasedCertCache that will use |backend|, which has - // previously been initialized, to store the certificate in the cache. - explicit DiskBasedCertCache(disk_cache::Backend* backend); - ~DiskBasedCertCache(); - - // Fetches the certificate associated with |key|. If the certificate is - // found within the cache, |cb| will be called with the certificate. - // Otherwise, |cb| will be called with NULL. Callers that wish to store - // a reference to the certificate need to use X509Certificate::DupOSCertHandle - // inside |cb|. - void Get(const std::string& key, const GetCallback& cb); - - // Stores |cert_handle| in the cache. If |cert_handle| is successfully stored, - // |cb| will be called with the key. If |cb| is called with an empty - // string, then |cert_handle| was not stored. - void Set(const X509Certificate::OSCertHandle cert_handle, - const SetCallback& cb); - - private: - class ReadWorker; - class WriteWorker; - - // ReadWorkerMap and WriteWorkerMap map cache keys to their - // corresponding Workers. - typedef base::hash_map ReadWorkerMap; - typedef base::hash_map WriteWorkerMap; - - // FinishedReadOperation and FinishedWriteOperation are used by callbacks - // given to the workers to signal the DiskBasedCertCache they have completed - // their work. - void FinishedReadOperation(const std::string& key); - void FinishedWriteOperation(const std::string& key); - - ReadWorkerMap read_worker_map_; - WriteWorkerMap write_worker_map_; - - disk_cache::Backend* backend_; - base::WeakPtrFactory weak_factory_; - DISALLOW_COPY_AND_ASSIGN(DiskBasedCertCache); -}; - -} // namespace net - -#endif // NET_HTTP_DISK_BASED_CERT_CACHE_H diff --git a/net/http/disk_based_cert_cache_unittest.cc b/net/http/disk_based_cert_cache_unittest.cc deleted file mode 100644 index 72f2f79b8b3d3..0000000000000 --- a/net/http/disk_based_cert_cache_unittest.cc +++ /dev/null @@ -1,476 +0,0 @@ -// Copyright 2014 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/http/disk_based_cert_cache.h" - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "net/base/completion_callback.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/base/test_data_directory.h" -#include "net/disk_cache/memory/mem_backend_impl.h" -#include "net/http/mock_http_cache.h" -#include "net/test/cert_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -// Testing the DiskBasedCertCache requires constant use of the -// certificates in GetTestCertsDirectory(). The TestCertMetaData -// struct stores metadata relevant to the DiskBasedCertCache for -// each used test certificate. -struct TestCertMetaData { - const char* file_name; - const char* cache_key; -}; - -const TestCertMetaData kCert1 = { - "root_ca_cert.pem", "cert:4C005EF1CF45F80D4A5A2BCFB00D4F198121E8D4"}; - -const TestCertMetaData kCert2 = { - "ok_cert.pem", "cert:9174C7CB9E4919604E7B1BFC430E4929DA45F65F"}; - -// MockTransactions are required to use the MockDiskCache backend. -// |key| is a cache key, and is equivalent to the key that will be -// used to store or retrieve certificates in the cache. |test_mode| -// is an integer that is used to indicate properties of the test -// transaction, mostly whether or not it is synchronous. -// For testing the DiskBasedCertCache, other data members of the struct -// are irrelevant. Only one MockTransaction per certificate can be used -// at a time. -MockTransaction CreateMockTransaction(const char* key, int test_mode) { - MockTransaction transaction = {key, "", base::Time(), "", LOAD_NORMAL, - "", "", base::Time(), "", test_mode, - NULL, 0, OK}; - - return transaction; -} - -// Helper class, for use with DiskBasedCertCache::Get, that will ensure that -// the returned certificate handle is kept alive after the callback has been -// executed and allow a user to WaitForResult of DiskBasedCertCache::Get. -class TestGetCallback { - public: - TestGetCallback() : cert_handle_(NULL) {} - ~TestGetCallback() { - if (cert_handle_) - X509Certificate::FreeOSCertHandle(cert_handle_); - } - - // Blocks until the underlying Get() operation has succeeded. - void WaitForResult() { cb_.WaitForResult(); } - - // Returns a Callback suitable for use with DiskBasedCertCache::Get(). The - // returned callback is only valid while the TestGetCallback object is still - // valid. - DiskBasedCertCache::GetCallback callback() { - return base::Bind(&TestGetCallback::OnGetComplete, base::Unretained(this)); - } - - // Returns the associated certificate handle. - const X509Certificate::OSCertHandle& cert_handle() const { - return cert_handle_; - } - - private: - void OnGetComplete(const X509Certificate::OSCertHandle handle) { - if (handle) - cert_handle_ = X509Certificate::DupOSCertHandle(handle); - cb_.callback().Run(OK); - } - - TestCompletionCallback cb_; - X509Certificate::OSCertHandle cert_handle_; -}; - -// Helper class, for use with DiskBasedCertCache::Set, that will store the -// returned key and allow a user to WaitForResult of DiskBasedCertCache::Set. -class TestSetCallback { - public: - TestSetCallback() {} - ~TestSetCallback() {} - - // Blocks until the underlying Set() operation has succeeded. - void WaitForResult() { cb_.WaitForResult(); } - - // Returns a Callback suitable for use with DiskBasedCertCache::Set(). The - // returned callback is only valid while the TestSetCallback object is still - // valid. - DiskBasedCertCache::SetCallback callback() { - return base::Bind(&TestSetCallback::OnSetComplete, base::Unretained(this)); - } - - // Returns the associated certificate handle. - const std::string& key() const { return key_; } - - private: - void OnSetComplete(const std::string& key) { - key_ = key; - cb_.callback().Run(OK); - } - - TestCompletionCallback cb_; - std::string key_; -}; - -// Stores the certificate corresponding to |cert_data| in |backend|. If -// |corrupt_data| is true, the certificate will be imported with errors -// so as to mimic a corrupted file on disk. -void ImportCert(disk_cache::Backend* backend, - const TestCertMetaData& cert_data, - bool corrupt_data) { - disk_cache::Entry* entry; - TestCompletionCallback callback; - int rv = - backend->CreateEntry(cert_data.cache_key, &entry, callback.callback()); - EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name)); - std::string write_data; - bool encoded = - X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data); - ASSERT_TRUE(encoded); - if (corrupt_data) { - for (size_t i = 0; i < write_data.size(); i += 20) - ++write_data[i]; - } - scoped_refptr buffer(new IOBuffer(write_data.size())); - memcpy(buffer->data(), write_data.data(), write_data.size()); - rv = entry->WriteData(0 /* index */, - 0 /* offset */, - buffer, - write_data.size(), - callback.callback(), - true /* truncate */); - ASSERT_EQ(static_cast(write_data.size()), callback.GetResult(rv)); - entry->Close(); -} - -// Checks that the the certificate corresponding to |cert_data| is an existing, -// correctly cached entry in |backend|. -void CheckCertCached(disk_cache::Backend* backend, - const TestCertMetaData& cert_data) { - disk_cache::Entry* entry; - TestCompletionCallback callback; - int rv = backend->OpenEntry(cert_data.cache_key, &entry, callback.callback()); - EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name)); - std::string write_data; - bool encoded = - X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data); - ASSERT_TRUE(encoded); - int entry_size = entry->GetDataSize(0 /* index */); - scoped_refptr buffer(new IOBuffer(entry_size)); - rv = entry->ReadData( - 0 /* index */, 0 /* offset */, buffer, entry_size, callback.callback()); - EXPECT_EQ(entry_size, callback.GetResult(rv)); - X509Certificate::OSCertHandle cached_cert_handle = - X509Certificate::CreateOSCertHandleFromBytes(buffer->data(), entry_size); - EXPECT_TRUE(X509Certificate::IsSameOSCert(cached_cert_handle, - cert->os_cert_handle())); -} - -} // namespace - -// ---------------------------------------------------------------------------- - -// Tests that a certificate can be stored in the cache. -TEST(DiskBasedCertCache, SetCert) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - TestSetCallback set_callback; - - cache.Set(cert->os_cert_handle(), set_callback.callback()); - set_callback.WaitForResult(); - EXPECT_EQ(kCert1.cache_key, set_callback.key()); - ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1)); -} - -// Tests that a certificate can be retrieved from the cache. -TEST(DiskBasedCertCache, GetCert) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - ASSERT_NO_FATAL_FAILURE( - ImportCert(&backend, kCert1, false /* not corrupted */)); - DiskBasedCertCache cache(&backend); - TestGetCallback get_callback; - - cache.Get(kCert1.cache_key, get_callback.callback()); - get_callback.WaitForResult(); - - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(), - cert->os_cert_handle())); -} - -// Tests that the DiskBasedCertCache successfully writes to the cache -// if the cache acts synchronously -TEST(DiskBasedCertCache, SyncSet) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - - TestSetCallback set_callback; - cache.Set(cert->os_cert_handle(), set_callback.callback()); - set_callback.WaitForResult(); - EXPECT_EQ(kCert1.cache_key, set_callback.key()); - ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1)); -} - -// Tests that the DiskBasedCertCache successfully reads from the cache -// if the cache acts synchronously -TEST(DiskBasedCertCache, SyncGet) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL)); - MockDiskCache backend; - ASSERT_NO_FATAL_FAILURE( - (ImportCert(&backend, kCert1, false /* not corrupted */))); - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - - TestGetCallback get_callback; - cache.Get(kCert1.cache_key, get_callback.callback()); - get_callback.WaitForResult(); - EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(), - cert->os_cert_handle())); -} - -// Tests that Get will fail on a corrupted certificate. -TEST(DiskBasedCertCache, GetBrokenCert) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - ASSERT_NO_FATAL_FAILURE(ImportCert(&backend, kCert1, true /* corrupted */)); - DiskBasedCertCache cache(&backend); - TestGetCallback get_callback; - - cache.Get(kCert1.cache_key, get_callback.callback()); - get_callback.WaitForResult(); - - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - EXPECT_FALSE(get_callback.cert_handle()); -} - -// Tests that attempting to retrieve a cert that is not in the cache will -// return NULL. -TEST(DiskBasedCertCache, GetUncachedCert) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - TestGetCallback get_callback; - - cache.Get(kCert1.cache_key, get_callback.callback()); - get_callback.WaitForResult(); - EXPECT_EQ(NULL, get_callback.cert_handle()); -} - -// Issues two requests to store a certificate in the cache -// (simultaneously), and checks that the DiskBasedCertCache stores the -// certificate to the cache (in one write rather than two). -TEST(DiskBasedCertCache, SetMultiple) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - TestSetCallback set_callback1, set_callback2; - - // Behind the scenes, these two operations will be combined - // into one operation. IgnoreCallbacks guarantees that the - // first Set operation is not yet complete when the second Set is - // called, and then IgnoreCallbacks(false) continues the - // (combined) operation in the |cache|. - MockDiskEntry::IgnoreCallbacks(true); - cache.Set(cert->os_cert_handle(), set_callback1.callback()); - cache.Set(cert->os_cert_handle(), set_callback2.callback()); - MockDiskEntry::IgnoreCallbacks(false); - - set_callback1.WaitForResult(); - set_callback2.WaitForResult(); - EXPECT_EQ(set_callback1.key(), set_callback2.key()); - ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1)); -} - -// Issues two requests to store a certificate in the cache -// because the first transaction finishes before the second -// one is issued, the first cache write is overwritten. -TEST(DiskBasedCertCache, SetOverwrite) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - backend.set_double_create_check(false); - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - TestSetCallback set_callback1, set_callback2; - - cache.Set(cert->os_cert_handle(), set_callback1.callback()); - set_callback1.WaitForResult(); - cache.Set(cert->os_cert_handle(), set_callback2.callback()); - set_callback2.WaitForResult(); - - EXPECT_EQ(set_callback1.key(), set_callback2.key()); - ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1)); -} - -// Stores a certificate in the DiskBasedCertCache, then retrieves it -// and makes sure it was retrieved successfully. -TEST(DiskBasedCertCache, SimpleSetAndGet) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - TestSetCallback set_callback; - TestGetCallback get_callback; - - cache.Set(cert->os_cert_handle(), set_callback.callback()); - set_callback.WaitForResult(); - cache.Get(set_callback.key(), get_callback.callback()); - get_callback.WaitForResult(); - EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(), - cert->os_cert_handle())); -} - -// Tests some basic functionality of the DiskBasedCertCache, with multiple -// set and get operations. -TEST(DiskBasedCertCache, BasicUsage) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START)); - ScopedMockTransaction trans2( - CreateMockTransaction(kCert2.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert1( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - scoped_refptr cert2( - ImportCertFromFile(GetTestCertsDirectory(), kCert2.file_name)); - ASSERT_TRUE(cert1.get()); - ASSERT_TRUE(cert2.get()); - ASSERT_FALSE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(), - cert2->os_cert_handle())); - TestSetCallback set_callback1, set_callback2; - - // Callbacks are temporarily ignored here to guarantee the asynchronous - // operations of the DiskBasedCertCache are always executed in the same - // order. - MockDiskEntry::IgnoreCallbacks(true); - cache.Set(cert1->os_cert_handle(), set_callback1.callback()); - cache.Set(cert2->os_cert_handle(), set_callback2.callback()); - MockDiskEntry::IgnoreCallbacks(false); - set_callback1.WaitForResult(); - set_callback2.WaitForResult(); - - TestGetCallback get_callback1, get_callback2; - - MockDiskEntry::IgnoreCallbacks(true); - cache.Get(set_callback1.key(), get_callback1.callback()); - cache.Get(set_callback2.key(), get_callback2.callback()); - MockDiskEntry::IgnoreCallbacks(false); - get_callback1.WaitForResult(); - get_callback2.WaitForResult(); - - EXPECT_TRUE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(), - get_callback1.cert_handle())); - EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2->os_cert_handle(), - get_callback2.cert_handle())); -} - -// Test the result of simultaneous requests to store and retrieve a -// certificate from the cache, with the get operation attempting to -// open the cache first and therefore failing to open the entry. -TEST(DiskBasedCertCache, SimultaneousGetSet) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - - TestGetCallback get_callback; - TestSetCallback set_callback; - - MockDiskEntry::IgnoreCallbacks(true); - cache.Get(kCert1.cache_key, get_callback.callback()); - cache.Set(cert->os_cert_handle(), set_callback.callback()); - MockDiskEntry::IgnoreCallbacks(false); - get_callback.WaitForResult(); - set_callback.WaitForResult(); - - EXPECT_EQ(NULL, get_callback.cert_handle()); - EXPECT_EQ(kCert1.cache_key, set_callback.key()); -} - -// Test the result of simultaneous requests to store and retrieve a -// certificate from the cache, with the get operation opening the cache -// after the set operation, leading to a successful read. -TEST(DiskBasedCertCache, SimultaneousSetGet) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START)); - MockDiskCache backend; - DiskBasedCertCache cache(&backend); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - - TestSetCallback set_callback; - TestGetCallback get_callback; - - MockDiskEntry::IgnoreCallbacks(true); - cache.Set(cert->os_cert_handle(), set_callback.callback()); - cache.Get(kCert1.cache_key, get_callback.callback()); - MockDiskEntry::IgnoreCallbacks(false); - set_callback.WaitForResult(); - get_callback.WaitForResult(); - - EXPECT_EQ(kCert1.cache_key, set_callback.key()); - EXPECT_TRUE(X509Certificate::IsSameOSCert(cert->os_cert_handle(), - get_callback.cert_handle())); -} - -// Tests that the DiskBasedCertCache can be deleted without issues when -// there are pending operations in the disk cache. -TEST(DiskBasedCertCache, DeletedCertCache) { - ScopedMockTransaction trans1( - CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL)); - MockDiskCache backend; - scoped_ptr cache(new DiskBasedCertCache(&backend)); - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name)); - ASSERT_TRUE(cert.get()); - TestSetCallback set_callback; - - cache->Set(cert->os_cert_handle(), set_callback.callback()); - cache.reset(); - set_callback.WaitForResult(); - EXPECT_EQ(std::string(), set_callback.key()); -} - -} // namespace net diff --git a/net/net.gypi b/net/net.gypi index 43d7121cd2d21..6eb846899b174 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -565,8 +565,6 @@ 'ftp/ftp_util.h', 'http/des.cc', 'http/des.h', - 'http/disk_based_cert_cache.cc', - 'http/disk_based_cert_cache.h', 'http/disk_cache_based_quic_server_info.cc', 'http/disk_cache_based_quic_server_info.h', 'http/failing_http_transaction_factory.cc', @@ -1343,7 +1341,6 @@ 'ftp/ftp_network_transaction_unittest.cc', 'ftp/ftp_util_unittest.cc', 'http/des_unittest.cc', - 'http/disk_based_cert_cache_unittest.cc', 'http/disk_cache_based_quic_server_info_unittest.cc', 'http/http_auth_cache_unittest.cc', 'http/http_auth_challenge_tokenizer_unittest.cc',