From f16532a7c0277e1876d4b8c75992faeef7e5867e Mon Sep 17 00:00:00 2001 From: "agl@chromium.org" <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> Date: Wed, 15 Dec 2010 20:07:39 +0000 Subject: [PATCH] net: fix callbacks in DiskCacheBasedSSLHostInfo Previously, DiskCacheBasedSSLHostInfo had a couple of problems: * I had assumed that the disk cache was taking references to the callback. It wasn't. * Even if it were, I was passing pointers into DiskCacheBasedSSLHostInfo which needed to be live for the duration of the callback. This change switches to a custom callback class which doesn't need reference counting and which contains pointer members that remain live for the duration of the callback. BUG=63867 TEST=Navigate to an HTTPS page with Snap Start running and no network connection. http://codereview.chromium.org/5826001/ git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69305 0039d316-1c4b-4281-b951-d872f2087c98 --- net/http/disk_cache_based_ssl_host_info.cc | 37 ++++++++---- net/http/disk_cache_based_ssl_host_info.h | 70 ++++++++++++++++------ 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc index cd1cac8ca0747..2b83f5618c074 100644 --- a/net/http/disk_cache_based_ssl_host_info.cc +++ b/net/http/disk_cache_based_ssl_host_info.cc @@ -17,9 +17,9 @@ DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo( const SSLConfig& ssl_config, HttpCache* http_cache) : SSLHostInfo(hostname, ssl_config), - callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>( - ALLOW_THIS_IN_INITIALIZER_LIST(this), - &DiskCacheBasedSSLHostInfo::DoLoop)), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + callback_(new CallbackImpl(weak_ptr_factory_.GetWeakPtr(), + &DiskCacheBasedSSLHostInfo::DoLoop)), state_(GET_BACKEND), ready_(false), hostname_(hostname), @@ -39,7 +39,8 @@ DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() { DCHECK(!user_callback_); if (entry_) entry_->Close(); - callback_->Cancel(); + if (!IsCallbackPending()) + delete callback_; } std::string DiskCacheBasedSSLHostInfo::key() const { @@ -92,13 +93,27 @@ void DiskCacheBasedSSLHostInfo::DoLoop(int rv) { } while (rv != ERR_IO_PENDING && state_ != NONE); } +bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const { + switch (state_) { + case GET_BACKEND_COMPLETE: + case OPEN_COMPLETE: + case READ_COMPLETE: + case CREATE_COMPLETE: + case WRITE_COMPLETE: + return true; + default: + return false; + } +} + int DiskCacheBasedSSLHostInfo::DoGetBackend() { state_ = GET_BACKEND_COMPLETE; - return http_cache_->GetBackend(&backend_, callback_.get()); + return http_cache_->GetBackend(callback_->backend_pointer(), callback_); } int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) { if (rv == OK) { + backend_ = callback_->backend(); state_ = OPEN; } else { state_ = WAIT_FOR_DATA_READY_DONE; @@ -108,11 +123,12 @@ int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) { int DiskCacheBasedSSLHostInfo::DoOpen() { state_ = OPEN_COMPLETE; - return backend_->OpenEntry(key(), &entry_, callback_.get()); + return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_); } int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) { if (rv == OK) { + entry_ = callback_->entry(); state_ = READ; } else { state_ = WAIT_FOR_DATA_READY_DONE; @@ -131,7 +147,7 @@ int DiskCacheBasedSSLHostInfo::DoRead() { read_buffer_ = new IOBuffer(size); state_ = READ_COMPLETE; return entry_->ReadData(0 /* index */, 0 /* offset */, read_buffer_, - size, callback_.get()); + size, callback_); } int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) { @@ -195,13 +211,14 @@ void DiskCacheBasedSSLHostInfo::Persist() { int DiskCacheBasedSSLHostInfo::DoCreate() { DCHECK(entry_ == NULL); state_ = CREATE_COMPLETE; - return backend_->CreateEntry(key(), &entry_, callback_.get()); + return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_); } int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) { if (rv != OK) { state_ = SET_DONE; } else { + entry_ = callback_->entry(); state_ = WRITE; } return OK; @@ -211,9 +228,9 @@ int DiskCacheBasedSSLHostInfo::DoWrite() { write_buffer_ = new IOBuffer(new_data_.size()); memcpy(write_buffer_->data(), new_data_.data(), new_data_.size()); state_ = WRITE_COMPLETE; + return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_, - new_data_.size(), callback_.get(), - true /* truncate */); + new_data_.size(), callback_, true /* truncate */); } int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) { diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h index 1d53b909dffbc..430931aec70a1 100644 --- a/net/http/disk_cache_based_ssl_host_info.h +++ b/net/http/disk_cache_based_ssl_host_info.h @@ -10,6 +10,7 @@ #include "base/lock.h" #include "base/non_thread_safe.h" #include "base/scoped_ptr.h" +#include "base/weak_ptr.h" #include "net/base/completion_callback.h" #include "net/disk_cache/disk_cache.h" #include "net/socket/ssl_host_info.h" @@ -36,7 +37,53 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo, virtual void Persist(); private: + enum State { + GET_BACKEND, + GET_BACKEND_COMPLETE, + OPEN, + OPEN_COMPLETE, + READ, + READ_COMPLETE, + WAIT_FOR_DATA_READY_DONE, + CREATE, + CREATE_COMPLETE, + WRITE, + WRITE_COMPLETE, + SET_DONE, + NONE, + }; + ~DiskCacheBasedSSLHostInfo(); + + class CallbackImpl : public CallbackRunner<Tuple1<int> > { + public: + CallbackImpl(const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj, + void (DiskCacheBasedSSLHostInfo::*meth) (int)) + : obj_(obj), + meth_(meth) { + } + + virtual void RunWithParams(const Tuple1<int>& params) { + if (!obj_) { + delete this; + } else { + DispatchToMethod(obj_.get(), meth_, params); + } + } + + disk_cache::Backend** backend_pointer() { return &backend_; } + disk_cache::Entry** entry_pointer() { return &entry_; } + disk_cache::Backend* backend() const { return backend_; } + disk_cache::Entry* entry() const { return entry_; } + + protected: + base::WeakPtr<DiskCacheBasedSSLHostInfo> obj_; + void (DiskCacheBasedSSLHostInfo::*meth_) (int); + + disk_cache::Backend* backend_; + disk_cache::Entry* entry_; + }; + std::string key() const; void DoLoop(int rv); @@ -58,31 +105,18 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo, // SetDone is the terminal state of the write operation. int SetDone(); - enum State { - GET_BACKEND, - GET_BACKEND_COMPLETE, - OPEN, - OPEN_COMPLETE, - READ, - READ_COMPLETE, - WAIT_FOR_DATA_READY_DONE, - CREATE, - CREATE_COMPLETE, - WRITE, - WRITE_COMPLETE, - SET_DONE, - NONE, - }; + // IsCallbackPending returns true if we have a pending callback. + bool IsCallbackPending() const; - scoped_refptr<CancelableCompletionCallback<DiskCacheBasedSSLHostInfo> > - callback_; + base::WeakPtrFactory<DiskCacheBasedSSLHostInfo> weak_ptr_factory_; + CallbackImpl* callback_; State state_; bool ready_; std::string new_data_; const std::string hostname_; HttpCache* const http_cache_; disk_cache::Backend* backend_; - disk_cache::Entry *entry_; + disk_cache::Entry* entry_; CompletionCallback* user_callback_; scoped_refptr<net::IOBuffer> read_buffer_; scoped_refptr<net::IOBuffer> write_buffer_; -- GitLab