Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: net/http/disk_cache_based_ssl_host_info.cc

Issue 135373002: Added SSLHostInfo. Storing of server host info to our standard disk cache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed wtc's comments Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/bind.h"
8 #include "base/callback.h"
9 #include "base/logging.h"
10 #include "net/base/completion_callback.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13 #include "net/http/http_cache.h"
14 #include "net/http/http_network_session.h"
15
16 namespace net {
17
18 // Some APIs inside disk_cache take a handle that the caller must keep alive
19 // until the API has finished its asynchronous execution.
20 //
21 // Unfortunately, DiskCacheBasedSSLHostInfo may be deleted before the
22 // operation completes causing a use-after-free.
23 //
24 // This data shim struct is meant to provide a location for the disk_cache
25 // APIs to write into even if the originating DiskCacheBasedSSLHostInfo
26 // object has been deleted. The lifetime for instances of this struct
27 // should be bound to the CompletionCallback that is passed to the disk_cache
28 // API. We do this by binding an instance of this struct to an unused
29 // parameter for OnIOComplete() using base::Owned().
30 //
31 // This is a hack. A better fix is to make it so that the disk_cache APIs
32 // take a Callback to a mutator for setting the output value rather than
33 // writing into a raw handle. Then the caller can just pass in a Callback
34 // bound to WeakPtr for itself. This callback would correctly "no-op" itself
35 // when the DiskCacheBasedSSLHostInfo object is deleted.
36 //
37 // TODO(ajwong): Change disk_cache's API to return results via Callback.
38 struct DiskCacheBasedSSLHostInfo::CacheOperationDataShim {
39 CacheOperationDataShim() : backend(NULL), entry(NULL) {}
40
41 disk_cache::Backend* backend;
42 disk_cache::Entry* entry;
43 };
44
45 DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo(
46 const std::string& hostname,
47 const SSLConfig& ssl_config,
48 CertVerifier* cert_verifier,
49 HttpCache* http_cache)
50 : SSLHostInfo(hostname, ssl_config, cert_verifier),
51 weak_factory_(this),
52 data_shim_(new CacheOperationDataShim()),
53 io_callback_(
54 base::Bind(&DiskCacheBasedSSLHostInfo::OnIOComplete,
55 weak_factory_.GetWeakPtr(),
56 base::Owned(data_shim_))), // Ownership assigned.
57 state_(GET_BACKEND),
58 ready_(false),
59 found_entry_(false),
60 hostname_(hostname),
61 http_cache_(http_cache),
62 backend_(NULL),
63 entry_(NULL) {
64 }
65
66 void DiskCacheBasedSSLHostInfo::Start() {
67 DCHECK(CalledOnValidThread());
68 DCHECK_EQ(GET_BACKEND, state_);
69 DoLoop(OK);
70 }
71
72 int DiskCacheBasedSSLHostInfo::WaitForDataReady(
73 const CompletionCallback& callback) {
74 DCHECK(CalledOnValidThread());
75 DCHECK(state_ != GET_BACKEND);
76
77 if (ready_)
78 return OK;
79
80 if (!callback.is_null()) {
81 DCHECK(user_callback_.is_null());
82 user_callback_ = callback;
83 }
84
85 return ERR_IO_PENDING;
86 }
87
88 void DiskCacheBasedSSLHostInfo::Persist() {
89 DCHECK(CalledOnValidThread());
90 DCHECK(state_ != GET_BACKEND);
91
92 DCHECK(new_data_.empty());
93 CHECK(ready_);
94 DCHECK(user_callback_.is_null());
95 new_data_ = Serialize();
96
97 if (!backend_)
98 return;
99
100 state_ = CREATE_OR_OPEN;
101 DoLoop(OK);
102 }
103
104 DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() {
105 DCHECK(user_callback_.is_null());
106 if (entry_)
107 entry_->Close();
108 }
109
110 std::string DiskCacheBasedSSLHostInfo::key() const {
111 return "sslhostinfo:" + hostname_;
112 }
113
114 void DiskCacheBasedSSLHostInfo::OnIOComplete(CacheOperationDataShim* unused,
115 int rv) {
116 rv = DoLoop(rv);
117 if (rv != ERR_IO_PENDING && !user_callback_.is_null()) {
118 CompletionCallback callback = user_callback_;
119 user_callback_.Reset();
120 callback.Run(rv);
121 }
122 }
123
124 int DiskCacheBasedSSLHostInfo::DoLoop(int rv) {
125 do {
126 switch (state_) {
127 case GET_BACKEND:
128 rv = DoGetBackend();
129 break;
130 case GET_BACKEND_COMPLETE:
131 rv = DoGetBackendComplete(rv);
132 break;
133 case OPEN:
134 rv = DoOpen();
135 break;
136 case OPEN_COMPLETE:
137 rv = DoOpenComplete(rv);
138 break;
139 case READ:
140 rv = DoRead();
141 break;
142 case READ_COMPLETE:
143 rv = DoReadComplete(rv);
144 break;
145 case WAIT_FOR_DATA_READY_DONE:
146 rv = DoWaitForDataReadyDone();
147 break;
148 case CREATE_OR_OPEN:
149 rv = DoCreateOrOpen();
150 break;
151 case CREATE_OR_OPEN_COMPLETE:
152 rv = DoCreateOrOpenComplete(rv);
153 break;
154 case WRITE:
155 rv = DoWrite();
156 break;
157 case WRITE_COMPLETE:
158 rv = DoWriteComplete(rv);
159 break;
160 case SET_DONE:
161 rv = DoSetDone();
162 break;
163 default:
164 rv = OK;
165 NOTREACHED();
166 }
167 } while (rv != ERR_IO_PENDING && state_ != NONE);
168
169 return rv;
170 }
171
172 int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
173 if (rv == OK) {
174 backend_ = data_shim_->backend;
175 state_ = OPEN;
176 } else {
177 state_ = WAIT_FOR_DATA_READY_DONE;
178 }
179 return OK;
180 }
181
182 int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) {
183 if (rv == OK) {
184 entry_ = data_shim_->entry;
185 state_ = READ;
186 found_entry_ = true;
187 } else {
188 state_ = WAIT_FOR_DATA_READY_DONE;
189 }
190
191 return OK;
192 }
193
194 int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
195 if (rv > 0)
196 data_.assign(read_buffer_->data(), rv);
197
198 state_ = WAIT_FOR_DATA_READY_DONE;
199 return OK;
200 }
201
202 int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
203 state_ = SET_DONE;
204 return OK;
205 }
206
207 int DiskCacheBasedSSLHostInfo::DoCreateOrOpenComplete(int rv) {
208 if (rv != OK) {
209 state_ = SET_DONE;
210 } else {
211 entry_ = data_shim_->entry;
212 state_ = WRITE;
213 }
214 return OK;
215 }
216
217 int DiskCacheBasedSSLHostInfo::DoGetBackend() {
218 state_ = GET_BACKEND_COMPLETE;
219 return http_cache_->GetBackend(&data_shim_->backend, io_callback_);
220 }
221
222 int DiskCacheBasedSSLHostInfo::DoOpen() {
223 state_ = OPEN_COMPLETE;
224 return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
225 }
226
227 int DiskCacheBasedSSLHostInfo::DoRead() {
228 const int32 size = entry_->GetDataSize(0 /* index */);
229 if (!size) {
230 state_ = WAIT_FOR_DATA_READY_DONE;
231 return OK;
232 }
233
234 read_buffer_ = new IOBuffer(size);
235 state_ = READ_COMPLETE;
236 return entry_->ReadData(
237 0 /* index */, 0 /* offset */, read_buffer_, size, io_callback_);
238 }
239
240 int DiskCacheBasedSSLHostInfo::DoWrite() {
241 write_buffer_ = new IOBuffer(new_data_.size());
242 memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
243 state_ = WRITE_COMPLETE;
244
245 return entry_->WriteData(
246 0 /* index */, 0 /* offset */, write_buffer_, new_data_.size(),
247 io_callback_, true /* truncate */);
248 }
249
250 int DiskCacheBasedSSLHostInfo::DoCreateOrOpen() {
251 DCHECK(entry_ == NULL);
252 state_ = CREATE_OR_OPEN_COMPLETE;
253 if (found_entry_) {
254 return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
255 }
256
257 return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_);
258 }
259
260 int DiskCacheBasedSSLHostInfo::DoWaitForDataReadyDone() {
261 DCHECK(!ready_);
262 state_ = NONE;
263 ready_ = true;
264 // We close the entry because, if we shutdown before ::Persist is called,
265 // then we might leak a cache reference, which causes a DCHECK on shutdown.
266 if (entry_)
267 entry_->Close();
268 entry_ = NULL;
269 Parse(data_);
270 return OK;
271 }
272
273 int DiskCacheBasedSSLHostInfo::DoSetDone() {
274 if (entry_)
275 entry_->Close();
276 entry_ = NULL;
277 state_ = NONE;
278 return OK;
279 }
280
281 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698