• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CallbackImpl(const base::WeakPtr<DiskCacheBasedSSLHostInfo> & obj,void (DiskCacheBasedSSLHostInfo::* meth)(int))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 
~CallbackImpl()25 DiskCacheBasedSSLHostInfo::CallbackImpl::~CallbackImpl() {}
26 
RunWithParams(const Tuple1<int> & params)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 
DiskCacheBasedSSLHostInfo(const std::string & hostname,const SSLConfig & ssl_config,CertVerifier * cert_verifier,HttpCache * http_cache)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 
Start()54 void DiskCacheBasedSSLHostInfo::Start() {
55   DCHECK(CalledOnValidThread());
56   DCHECK_EQ(GET_BACKEND, state_);
57   DoLoop(OK);
58 }
59 
WaitForDataReady(CompletionCallback * callback)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 
Persist()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 
~DiskCacheBasedSSLHostInfo()89 DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() {
90   DCHECK(!user_callback_);
91   if (entry_)
92     entry_->Close();
93   if (!IsCallbackPending())
94     delete callback_;
95 }
96 
key() const97 std::string DiskCacheBasedSSLHostInfo::key() const {
98   return "sslhostinfo:" + hostname_;
99 }
100 
DoLoop(int rv)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 
DoGetBackendComplete(int rv)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 
DoOpenComplete(int rv)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 
DoReadComplete(int rv)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 
DoWriteComplete(int rv)176 int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
177   state_ = SET_DONE;
178   return OK;
179 }
180 
DoCreateComplete(int rv)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 
DoGetBackend()191 int DiskCacheBasedSSLHostInfo::DoGetBackend() {
192   state_ = GET_BACKEND_COMPLETE;
193   return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
194 }
195 
DoOpen()196 int DiskCacheBasedSSLHostInfo::DoOpen() {
197   state_ = OPEN_COMPLETE;
198   return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
199 }
200 
DoRead()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 
DoWrite()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 
DoCreate()223 int DiskCacheBasedSSLHostInfo::DoCreate() {
224   DCHECK(entry_ == NULL);
225   state_ = CREATE_COMPLETE;
226   return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
227 }
228 
WaitForDataReadyDone()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 
SetDone()250 int DiskCacheBasedSSLHostInfo::SetDone() {
251   if (entry_)
252     entry_->Close();
253   entry_ = NULL;
254   state_ = NONE;
255   return OK;
256 }
257 
IsCallbackPending() const258 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