Home | History | Annotate | Download | only in http
      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