OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/appcache/appcache_response.h" | 5 #include "content/browser/appcache/appcache_response.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/pickle.h" | 12 #include "base/pickle.h" |
13 #include "base/profiler/scoped_tracker.h" | 13 #include "base/profiler/scoped_tracker.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "content/browser/appcache/appcache_storage.h" | 15 #include "content/browser/appcache/appcache_storage.h" |
16 #include "net/base/completion_callback.h" | 16 #include "net/base/completion_callback.h" |
17 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
19 | 19 |
20 namespace content { | 20 namespace content { |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // Disk cache entry data indices. | 24 // Disk cache entry data indices. |
25 enum { | 25 enum { kResponseInfoIndex, kResponseContentIndex, kResponseMetadataIndex }; |
26 kResponseInfoIndex, | |
27 kResponseContentIndex | |
28 }; | |
29 | 26 |
30 // An IOBuffer that wraps a pickle's data. Ownership of the | 27 // An IOBuffer that wraps a pickle's data. Ownership of the |
31 // pickle is transfered to the WrappedPickleIOBuffer object. | 28 // pickle is transfered to the WrappedPickleIOBuffer object. |
32 class WrappedPickleIOBuffer : public net::WrappedIOBuffer { | 29 class WrappedPickleIOBuffer : public net::WrappedIOBuffer { |
33 public: | 30 public: |
34 explicit WrappedPickleIOBuffer(const Pickle* pickle) : | 31 explicit WrappedPickleIOBuffer(const Pickle* pickle) : |
35 net::WrappedIOBuffer(reinterpret_cast<const char*>(pickle->data())), | 32 net::WrappedIOBuffer(reinterpret_cast<const char*>(pickle->data())), |
36 pickle_(pickle) { | 33 pickle_(pickle) { |
37 DCHECK(pickle->data()); | 34 DCHECK(pickle->data()); |
38 } | 35 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 void AppCacheResponseIO::OnRawIOComplete(int result) { | 129 void AppCacheResponseIO::OnRawIOComplete(int result) { |
133 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. | 130 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. |
134 tracked_objects::ScopedTracker tracking_profile( | 131 tracked_objects::ScopedTracker tracking_profile( |
135 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 132 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
136 "422516 AppCacheResponseIO::OnRawIOComplete")); | 133 "422516 AppCacheResponseIO::OnRawIOComplete")); |
137 | 134 |
138 DCHECK_NE(net::ERR_IO_PENDING, result); | 135 DCHECK_NE(net::ERR_IO_PENDING, result); |
139 OnIOComplete(result); | 136 OnIOComplete(result); |
140 } | 137 } |
141 | 138 |
| 139 void AppCacheResponseIO::OpenEntryIfNeeded() { |
| 140 int rv; |
| 141 AppCacheDiskCacheInterface::Entry** entry_ptr = NULL; |
| 142 if (entry_) { |
| 143 rv = net::OK; |
| 144 } else if (!disk_cache_) { |
| 145 rv = net::ERR_FAILED; |
| 146 } else { |
| 147 entry_ptr = new AppCacheDiskCacheInterface::Entry*; |
| 148 open_callback_ = |
| 149 base::Bind(&AppCacheResponseIO::OpenEntryCallback, |
| 150 weak_factory_.GetWeakPtr(), base::Owned(entry_ptr)); |
| 151 rv = disk_cache_->OpenEntry(response_id_, entry_ptr, open_callback_); |
| 152 } |
| 153 |
| 154 if (rv != net::ERR_IO_PENDING) |
| 155 OpenEntryCallback(entry_ptr, rv); |
| 156 } |
| 157 |
| 158 void AppCacheResponseIO::OpenEntryCallback( |
| 159 AppCacheDiskCacheInterface::Entry** entry, int rv) { |
| 160 DCHECK(info_buffer_.get() || buffer_.get()); |
| 161 |
| 162 if (!open_callback_.is_null()) { |
| 163 if (rv == net::OK) { |
| 164 DCHECK(entry); |
| 165 entry_ = *entry; |
| 166 } |
| 167 open_callback_.Reset(); |
| 168 } |
| 169 OnOpenEntryComplete(); |
| 170 } |
| 171 |
142 | 172 |
143 // AppCacheResponseReader ---------------------------------------------- | 173 // AppCacheResponseReader ---------------------------------------------- |
144 | 174 |
145 AppCacheResponseReader::AppCacheResponseReader( | 175 AppCacheResponseReader::AppCacheResponseReader( |
146 int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache) | 176 int64 response_id, |
| 177 int64 group_id, |
| 178 AppCacheDiskCacheInterface* disk_cache) |
147 : AppCacheResponseIO(response_id, group_id, disk_cache), | 179 : AppCacheResponseIO(response_id, group_id, disk_cache), |
148 range_offset_(0), | 180 range_offset_(0), |
149 range_length_(kint32max), | 181 range_length_(kint32max), |
150 read_position_(0), | 182 read_position_(0), |
| 183 reading_metadata_size_(0), |
151 weak_factory_(this) { | 184 weak_factory_(this) { |
152 } | 185 } |
153 | 186 |
154 AppCacheResponseReader::~AppCacheResponseReader() { | 187 AppCacheResponseReader::~AppCacheResponseReader() { |
155 } | 188 } |
156 | 189 |
157 void AppCacheResponseReader::ReadInfo(HttpResponseInfoIOBuffer* info_buf, | 190 void AppCacheResponseReader::ReadInfo(HttpResponseInfoIOBuffer* info_buf, |
158 const net::CompletionCallback& callback) { | 191 const net::CompletionCallback& callback) { |
159 DCHECK(!callback.is_null()); | 192 DCHECK(!callback.is_null()); |
160 DCHECK(!IsReadPending()); | 193 DCHECK(!IsReadPending()); |
161 DCHECK(info_buf); | 194 DCHECK(info_buf); |
162 DCHECK(!info_buf->http_info.get()); | 195 DCHECK(!info_buf->http_info.get()); |
163 DCHECK(!buffer_.get()); | 196 DCHECK(!buffer_.get()); |
164 DCHECK(!info_buffer_.get()); | 197 DCHECK(!info_buffer_.get()); |
165 | 198 |
166 info_buffer_ = info_buf; | 199 info_buffer_ = info_buf; |
167 callback_ = callback; // cleared on completion | 200 callback_ = callback; // cleared on completion |
168 OpenEntryIfNeededAndContinue(); | 201 OpenEntryIfNeeded(); |
169 } | 202 } |
170 | 203 |
171 void AppCacheResponseReader::ContinueReadInfo() { | 204 void AppCacheResponseReader::ContinueReadInfo() { |
172 if (!entry_) { | |
173 ScheduleIOCompletionCallback(net::ERR_CACHE_MISS); | |
174 return; | |
175 } | |
176 | |
177 int size = entry_->GetSize(kResponseInfoIndex); | 205 int size = entry_->GetSize(kResponseInfoIndex); |
178 if (size <= 0) { | 206 if (size <= 0) { |
179 ScheduleIOCompletionCallback(net::ERR_CACHE_MISS); | 207 ScheduleIOCompletionCallback(net::ERR_CACHE_MISS); |
180 return; | 208 return; |
181 } | 209 } |
182 | 210 |
183 buffer_ = new net::IOBuffer(size); | 211 buffer_ = new net::IOBuffer(size); |
184 ReadRaw(kResponseInfoIndex, 0, buffer_.get(), size); | 212 ReadRaw(kResponseInfoIndex, 0, buffer_.get(), size); |
185 } | 213 } |
186 | 214 |
187 void AppCacheResponseReader::ReadData(net::IOBuffer* buf, int buf_len, | 215 void AppCacheResponseReader::ReadData(net::IOBuffer* buf, int buf_len, |
188 const net::CompletionCallback& callback) { | 216 const net::CompletionCallback& callback) { |
189 DCHECK(!callback.is_null()); | 217 DCHECK(!callback.is_null()); |
190 DCHECK(!IsReadPending()); | 218 DCHECK(!IsReadPending()); |
191 DCHECK(buf); | 219 DCHECK(buf); |
192 DCHECK(buf_len >= 0); | 220 DCHECK(buf_len >= 0); |
193 DCHECK(!buffer_.get()); | 221 DCHECK(!buffer_.get()); |
194 DCHECK(!info_buffer_.get()); | 222 DCHECK(!info_buffer_.get()); |
195 | 223 |
196 buffer_ = buf; | 224 buffer_ = buf; |
197 buffer_len_ = buf_len; | 225 buffer_len_ = buf_len; |
198 callback_ = callback; // cleared on completion | 226 callback_ = callback; // cleared on completion |
199 OpenEntryIfNeededAndContinue(); | 227 OpenEntryIfNeeded(); |
200 } | 228 } |
201 | 229 |
202 void AppCacheResponseReader::ContinueReadData() { | 230 void AppCacheResponseReader::ContinueReadData() { |
203 if (!entry_) { | |
204 ScheduleIOCompletionCallback(net::ERR_CACHE_MISS); | |
205 return; | |
206 } | |
207 | |
208 if (read_position_ + buffer_len_ > range_length_) { | 231 if (read_position_ + buffer_len_ > range_length_) { |
209 // TODO(michaeln): What about integer overflows? | 232 // TODO(michaeln): What about integer overflows? |
210 DCHECK(range_length_ >= read_position_); | 233 DCHECK(range_length_ >= read_position_); |
211 buffer_len_ = range_length_ - read_position_; | 234 buffer_len_ = range_length_ - read_position_; |
212 } | 235 } |
213 ReadRaw(kResponseContentIndex, | 236 ReadRaw(kResponseContentIndex, |
214 range_offset_ + read_position_, | 237 range_offset_ + read_position_, |
215 buffer_.get(), | 238 buffer_.get(), |
216 buffer_len_); | 239 buffer_len_); |
217 } | 240 } |
218 | 241 |
219 void AppCacheResponseReader::SetReadRange(int offset, int length) { | 242 void AppCacheResponseReader::SetReadRange(int offset, int length) { |
220 DCHECK(!IsReadPending() && !read_position_); | 243 DCHECK(!IsReadPending() && !read_position_); |
221 range_offset_ = offset; | 244 range_offset_ = offset; |
222 range_length_ = length; | 245 range_length_ = length; |
223 } | 246 } |
224 | 247 |
225 void AppCacheResponseReader::OnIOComplete(int result) { | 248 void AppCacheResponseReader::OnIOComplete(int result) { |
226 if (result >= 0) { | 249 if (result >= 0) { |
227 if (info_buffer_.get()) { | 250 if (reading_metadata_size_) { |
| 251 DCHECK(reading_metadata_size_ == result); |
| 252 DCHECK(info_buffer_->http_info->metadata); |
| 253 reading_metadata_size_ = 0; |
| 254 } else if (info_buffer_.get()) { |
228 // Deserialize the http info structure, ensuring we got headers. | 255 // Deserialize the http info structure, ensuring we got headers. |
229 Pickle pickle(buffer_->data(), result); | 256 Pickle pickle(buffer_->data(), result); |
230 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo); | 257 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo); |
231 bool response_truncated = false; | 258 bool response_truncated = false; |
232 if (!info->InitFromPickle(pickle, &response_truncated) || | 259 if (!info->InitFromPickle(pickle, &response_truncated) || |
233 !info->headers.get()) { | 260 !info->headers.get()) { |
234 InvokeUserCompletionCallback(net::ERR_FAILED); | 261 InvokeUserCompletionCallback(net::ERR_FAILED); |
235 return; | 262 return; |
236 } | 263 } |
237 DCHECK(!response_truncated); | 264 DCHECK(!response_truncated); |
238 info_buffer_->http_info.reset(info.release()); | 265 info_buffer_->http_info.reset(info.release()); |
239 | 266 |
240 // Also return the size of the response body | 267 // Also return the size of the response body |
241 DCHECK(entry_); | 268 DCHECK(entry_); |
242 info_buffer_->response_data_size = | 269 info_buffer_->response_data_size = |
243 entry_->GetSize(kResponseContentIndex); | 270 entry_->GetSize(kResponseContentIndex); |
| 271 |
| 272 int64 metadata_size = entry_->GetSize(kResponseMetadataIndex); |
| 273 if (metadata_size > 0) { |
| 274 reading_metadata_size_ = metadata_size; |
| 275 info_buffer_->http_info->metadata = |
| 276 new net::IOBufferWithSize(metadata_size); |
| 277 ReadRaw(kResponseMetadataIndex, 0, |
| 278 info_buffer_->http_info->metadata.get(), metadata_size); |
| 279 return; |
| 280 } |
244 } else { | 281 } else { |
245 read_position_ += result; | 282 read_position_ += result; |
246 } | 283 } |
247 } | 284 } |
248 InvokeUserCompletionCallback(result); | 285 InvokeUserCompletionCallback(result); |
249 } | 286 } |
250 | 287 |
251 void AppCacheResponseReader::OpenEntryIfNeededAndContinue() { | 288 void AppCacheResponseReader::OnOpenEntryComplete() { |
252 int rv; | 289 if (!entry_) { |
253 AppCacheDiskCacheInterface::Entry** entry_ptr = NULL; | 290 ScheduleIOCompletionCallback(net::ERR_CACHE_MISS); |
254 if (entry_) { | 291 return; |
255 rv = net::OK; | |
256 } else if (!disk_cache_) { | |
257 rv = net::ERR_FAILED; | |
258 } else { | |
259 entry_ptr = new AppCacheDiskCacheInterface::Entry*; | |
260 open_callback_ = | |
261 base::Bind(&AppCacheResponseReader::OnOpenEntryComplete, | |
262 weak_factory_.GetWeakPtr(), base::Owned(entry_ptr)); | |
263 rv = disk_cache_->OpenEntry(response_id_, entry_ptr, open_callback_); | |
264 } | 292 } |
265 | |
266 if (rv != net::ERR_IO_PENDING) | |
267 OnOpenEntryComplete(entry_ptr, rv); | |
268 } | |
269 | |
270 void AppCacheResponseReader::OnOpenEntryComplete( | |
271 AppCacheDiskCacheInterface::Entry** entry, int rv) { | |
272 DCHECK(info_buffer_.get() || buffer_.get()); | |
273 | |
274 if (!open_callback_.is_null()) { | |
275 if (rv == net::OK) { | |
276 DCHECK(entry); | |
277 entry_ = *entry; | |
278 } | |
279 open_callback_.Reset(); | |
280 } | |
281 | |
282 if (info_buffer_.get()) | 293 if (info_buffer_.get()) |
283 ContinueReadInfo(); | 294 ContinueReadInfo(); |
284 else | 295 else |
285 ContinueReadData(); | 296 ContinueReadData(); |
286 } | 297 } |
287 | 298 |
288 // AppCacheResponseWriter ---------------------------------------------- | 299 // AppCacheResponseWriter ---------------------------------------------- |
289 | 300 |
290 AppCacheResponseWriter::AppCacheResponseWriter( | 301 AppCacheResponseWriter::AppCacheResponseWriter( |
291 int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache) | 302 int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache) |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 430 |
420 create_callback_.Reset(); | 431 create_callback_.Reset(); |
421 } | 432 } |
422 | 433 |
423 if (info_buffer_.get()) | 434 if (info_buffer_.get()) |
424 ContinueWriteInfo(); | 435 ContinueWriteInfo(); |
425 else | 436 else |
426 ContinueWriteData(); | 437 ContinueWriteData(); |
427 } | 438 } |
428 | 439 |
| 440 // AppCacheResponseMetadataWriter ---------------------------------------------- |
| 441 |
| 442 AppCacheResponseMetadataWriter::AppCacheResponseMetadataWriter( |
| 443 int64 response_id, |
| 444 int64 group_id, |
| 445 AppCacheDiskCacheInterface* disk_cache) |
| 446 : AppCacheResponseIO(response_id, group_id, disk_cache), |
| 447 write_amount_(0), |
| 448 weak_factory_(this) { |
| 449 } |
| 450 |
| 451 AppCacheResponseMetadataWriter::~AppCacheResponseMetadataWriter() { |
| 452 } |
| 453 |
| 454 void AppCacheResponseMetadataWriter::WriteMetadata( |
| 455 net::IOBuffer* buf, |
| 456 int buf_len, |
| 457 const net::CompletionCallback& callback) { |
| 458 DCHECK(!callback.is_null()); |
| 459 DCHECK(!IsIOPending()); |
| 460 DCHECK(buf); |
| 461 DCHECK(buf_len >= 0); |
| 462 DCHECK(!buffer_.get()); |
| 463 |
| 464 buffer_ = buf; |
| 465 write_amount_ = buf_len; |
| 466 callback_ = callback; // cleared on completion |
| 467 OpenEntryIfNeeded(); |
| 468 } |
| 469 |
| 470 void AppCacheResponseMetadataWriter::OnOpenEntryComplete() { |
| 471 if (!entry_) { |
| 472 ScheduleIOCompletionCallback(net::ERR_FAILED); |
| 473 return; |
| 474 } |
| 475 WriteRaw(kResponseMetadataIndex, 0, buffer_.get(), write_amount_); |
| 476 } |
| 477 |
| 478 void AppCacheResponseMetadataWriter::OnIOComplete(int result) { |
| 479 DCHECK(result < 0 || write_amount_ == result); |
| 480 InvokeUserCompletionCallback(result); |
| 481 } |
| 482 |
429 } // namespace content | 483 } // namespace content |
OLD | NEW |