1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/http/disk_cache_based_ssl_host_info.h" 6 7 #include "base/callback.h" 8 #include "base/logging.h" 9 #include "net/base/io_buffer.h" 10 #include "net/base/net_errors.h" 11 #include "net/http/http_cache.h" 12 #include "net/http/http_network_session.h" 13 14 namespace net { 15 16 DiskCacheBasedSSLHostInfo::CallbackImpl::CallbackImpl( 17 const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj, 18 void (DiskCacheBasedSSLHostInfo::*meth)(int)) 19 : obj_(obj), 20 meth_(meth), 21 backend_(NULL), 22 entry_(NULL) { 23 } 24 25 DiskCacheBasedSSLHostInfo::CallbackImpl::~CallbackImpl() {} 26 27 void DiskCacheBasedSSLHostInfo::CallbackImpl::RunWithParams( 28 const Tuple1<int>& params) { 29 if (!obj_) { 30 delete this; 31 } else { 32 DispatchToMethod(obj_.get(), meth_, params); 33 } 34 } 35 36 DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo( 37 const std::string& hostname, 38 const SSLConfig& ssl_config, 39 CertVerifier* cert_verifier, 40 HttpCache* http_cache) 41 : SSLHostInfo(hostname, ssl_config, cert_verifier), 42 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 43 callback_(new CallbackImpl(weak_ptr_factory_.GetWeakPtr(), 44 &DiskCacheBasedSSLHostInfo::DoLoop)), 45 state_(GET_BACKEND), 46 ready_(false), 47 hostname_(hostname), 48 http_cache_(http_cache), 49 backend_(NULL), 50 entry_(NULL), 51 user_callback_(NULL) { 52 } 53 54 void DiskCacheBasedSSLHostInfo::Start() { 55 DCHECK(CalledOnValidThread()); 56 DCHECK_EQ(GET_BACKEND, state_); 57 DoLoop(OK); 58 } 59 60 int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) { 61 DCHECK(CalledOnValidThread()); 62 DCHECK(state_ != GET_BACKEND); 63 64 if (ready_) 65 return OK; 66 if (callback) { 67 DCHECK(!user_callback_); 68 user_callback_ = callback; 69 } 70 return ERR_IO_PENDING; 71 } 72 73 void DiskCacheBasedSSLHostInfo::Persist() { 74 DCHECK(CalledOnValidThread()); 75 DCHECK(state_ != GET_BACKEND); 76 77 DCHECK(new_data_.empty()); 78 CHECK(ready_); 79 DCHECK(user_callback_ == NULL); 80 new_data_ = Serialize(); 81 82 if (!backend_) 83 return; 84 85 state_ = CREATE; 86 DoLoop(OK); 87 } 88 89 DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() { 90 DCHECK(!user_callback_); 91 if (entry_) 92 entry_->Close(); 93 if (!IsCallbackPending()) 94 delete callback_; 95 } 96 97 std::string DiskCacheBasedSSLHostInfo::key() const { 98 return "sslhostinfo:" + hostname_; 99 } 100 101 void DiskCacheBasedSSLHostInfo::DoLoop(int rv) { 102 do { 103 switch (state_) { 104 case GET_BACKEND: 105 rv = DoGetBackend(); 106 break; 107 case GET_BACKEND_COMPLETE: 108 rv = DoGetBackendComplete(rv); 109 break; 110 case OPEN: 111 rv = DoOpen(); 112 break; 113 case OPEN_COMPLETE: 114 rv = DoOpenComplete(rv); 115 break; 116 case READ: 117 rv = DoRead(); 118 break; 119 case READ_COMPLETE: 120 rv = DoReadComplete(rv); 121 break; 122 case WAIT_FOR_DATA_READY_DONE: 123 rv = WaitForDataReadyDone(); 124 break; 125 case CREATE: 126 rv = DoCreate(); 127 break; 128 case CREATE_COMPLETE: 129 rv = DoCreateComplete(rv); 130 break; 131 case WRITE: 132 rv = DoWrite(); 133 break; 134 case WRITE_COMPLETE: 135 rv = DoWriteComplete(rv); 136 break; 137 case SET_DONE: 138 rv = SetDone(); 139 break; 140 default: 141 rv = OK; 142 NOTREACHED(); 143 } 144 } while (rv != ERR_IO_PENDING && state_ != NONE); 145 } 146 147 int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) { 148 if (rv == OK) { 149 backend_ = callback_->backend(); 150 state_ = OPEN; 151 } else { 152 state_ = WAIT_FOR_DATA_READY_DONE; 153 } 154 return OK; 155 } 156 157 int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) { 158 if (rv == OK) { 159 entry_ = callback_->entry(); 160 state_ = READ; 161 } else { 162 state_ = WAIT_FOR_DATA_READY_DONE; 163 } 164 165 return OK; 166 } 167 168 int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) { 169 if (rv > 0) 170 data_ = std::string(read_buffer_->data(), rv); 171 172 state_ = WAIT_FOR_DATA_READY_DONE; 173 return OK; 174 } 175 176 int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) { 177 state_ = SET_DONE; 178 return OK; 179 } 180 181 int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) { 182 if (rv != OK) { 183 state_ = SET_DONE; 184 } else { 185 entry_ = callback_->entry(); 186 state_ = WRITE; 187 } 188 return OK; 189 } 190 191 int DiskCacheBasedSSLHostInfo::DoGetBackend() { 192 state_ = GET_BACKEND_COMPLETE; 193 return http_cache_->GetBackend(callback_->backend_pointer(), callback_); 194 } 195 196 int DiskCacheBasedSSLHostInfo::DoOpen() { 197 state_ = OPEN_COMPLETE; 198 return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_); 199 } 200 201 int DiskCacheBasedSSLHostInfo::DoRead() { 202 const int32 size = entry_->GetDataSize(0 /* index */); 203 if (!size) { 204 state_ = WAIT_FOR_DATA_READY_DONE; 205 return OK; 206 } 207 208 read_buffer_ = new IOBuffer(size); 209 state_ = READ_COMPLETE; 210 return entry_->ReadData(0 /* index */, 0 /* offset */, read_buffer_, 211 size, callback_); 212 } 213 214 int DiskCacheBasedSSLHostInfo::DoWrite() { 215 write_buffer_ = new IOBuffer(new_data_.size()); 216 memcpy(write_buffer_->data(), new_data_.data(), new_data_.size()); 217 state_ = WRITE_COMPLETE; 218 219 return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_, 220 new_data_.size(), callback_, true /* truncate */); 221 } 222 223 int DiskCacheBasedSSLHostInfo::DoCreate() { 224 DCHECK(entry_ == NULL); 225 state_ = CREATE_COMPLETE; 226 return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_); 227 } 228 229 int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() { 230 CompletionCallback* callback; 231 232 DCHECK(!ready_); 233 state_ = NONE; 234 ready_ = true; 235 callback = user_callback_; 236 user_callback_ = NULL; 237 // We close the entry because, if we shutdown before ::Persist is called, 238 // then we might leak a cache reference, which causes a DCHECK on shutdown. 239 if (entry_) 240 entry_->Close(); 241 entry_ = NULL; 242 Parse(data_); 243 244 if (callback) 245 callback->Run(OK); 246 247 return OK; 248 } 249 250 int DiskCacheBasedSSLHostInfo::SetDone() { 251 if (entry_) 252 entry_->Close(); 253 entry_ = NULL; 254 state_ = NONE; 255 return OK; 256 } 257 258 bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const { 259 switch (state_) { 260 case GET_BACKEND_COMPLETE: 261 case OPEN_COMPLETE: 262 case READ_COMPLETE: 263 case CREATE_COMPLETE: 264 case WRITE_COMPLETE: 265 return true; 266 default: 267 return false; 268 } 269 } 270 271 } // namespace net 272