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 "net/http/http_cache.h" | 5 #include "net/http/http_cache.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 | 10 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 virtual QuicServerInfo* GetForServer( | 285 virtual QuicServerInfo* GetForServer( |
286 const QuicServerId& server_id) OVERRIDE { | 286 const QuicServerId& server_id) OVERRIDE { |
287 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); | 287 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); |
288 } | 288 } |
289 | 289 |
290 private: | 290 private: |
291 HttpCache* const http_cache_; | 291 HttpCache* const http_cache_; |
292 }; | 292 }; |
293 | 293 |
294 //----------------------------------------------------------------------------- | 294 //----------------------------------------------------------------------------- |
295 | |
296 class HttpCache::AsyncValidation { | |
297 public: | |
298 AsyncValidation(const HttpRequestInfo& original_request, HttpCache* cache) | |
299 : request_(original_request), cache_(cache) {} | |
300 ~AsyncValidation() {} | |
301 | |
302 void Start(const BoundNetLog& net_log); | |
303 | |
304 private: | |
305 void OnStarted(int result); | |
306 void DoRead(); | |
307 void OnRead(int result); | |
308 | |
309 // Terminate this request with net error code |result|. Logs the transaction | |
310 // result and asks HttpCache to delete this object. | |
311 // If there was a client or server certificate error, it cannot be recovered | |
312 // asynchronously, so we need to prevent futures attempts to asynchronously | |
313 // fetch the resource. In this case, the cache entry is doomed. | |
314 void Terminate(int result); | |
315 | |
316 HttpRequestInfo request_; | |
317 scoped_refptr<IOBuffer> buf_; | |
318 CompletionCallback read_callback_; | |
319 scoped_ptr<Transaction> transaction_; | |
320 | |
321 // The HttpCache object owns this object. This object is always deleted before | |
322 // the pointer to the cache becomes invalid. | |
323 HttpCache* cache_; | |
324 | |
325 DISALLOW_COPY_AND_ASSIGN(AsyncValidation); | |
326 }; | |
327 | |
328 void HttpCache::AsyncValidation::Start(const BoundNetLog& net_log) { | |
329 transaction_.reset(new Transaction(IDLE, cache_)); | |
330 request_.load_flags |= LOAD_VALIDATE_CACHE; | |
331 // This use of base::Unretained is safe because |transaction_| is owned by | |
332 // this object. | |
333 read_callback_ = base::Bind(&AsyncValidation::OnRead, base::Unretained(this)); | |
334 // This use of base::Unretained is safe as above. | |
335 int rv = transaction_->Start( | |
336 &request_, | |
337 base::Bind(&AsyncValidation::OnStarted, base::Unretained(this)), | |
338 net_log); | |
339 | |
340 if (rv == ERR_IO_PENDING) | |
341 return; | |
342 | |
343 OnStarted(rv); | |
344 } | |
345 | |
346 void HttpCache::AsyncValidation::OnStarted(int result) { | |
347 if (result != OK) { | |
348 DVLOG(1) << "Asynchronous transaction start failed for " << request_.url; | |
349 Terminate(result); | |
350 return; | |
351 } | |
352 | |
353 DoRead(); | |
354 } | |
355 | |
356 void HttpCache::AsyncValidation::DoRead() { | |
357 const size_t kBufSize = 4096; | |
358 if (!buf_) | |
359 buf_ = new IOBuffer(kBufSize); | |
360 | |
361 int rv = 0; | |
362 while (rv > 0) { | |
yhirano
2014/08/26 07:52:01
dead code :)
Adam Rice
2014/08/26 13:38:41
Amazing! This doesn't seem to make any difference
| |
363 rv = transaction_->Read(buf_.get(), kBufSize, read_callback_); | |
364 } | |
365 | |
366 if (rv == ERR_IO_PENDING) | |
367 return; | |
368 | |
369 OnRead(rv); | |
370 } | |
371 | |
372 void HttpCache::AsyncValidation::OnRead(int result) { | |
373 if (result > 0) { | |
374 DoRead(); | |
375 return; | |
376 } | |
377 Terminate(result); | |
378 } | |
379 | |
380 void HttpCache::AsyncValidation::Terminate(int result) { | |
381 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED || IsCertificateError(result)) | |
382 cache_->DoomEntry(transaction_->key(), transaction_.get()); | |
383 transaction_->net_log().EndEventWithNetErrorCode( | |
384 NetLog::TYPE_ASYNC_REVALIDATION, result); | |
385 cache_->DeleteAsyncValidation(this); | |
386 // |this| is deleted. | |
387 } | |
388 | |
389 //----------------------------------------------------------------------------- | |
295 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, | 390 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, |
296 BackendFactory* backend_factory) | 391 BackendFactory* backend_factory) |
297 : net_log_(params.net_log), | 392 : net_log_(params.net_log), |
298 backend_factory_(backend_factory), | 393 backend_factory_(backend_factory), |
299 building_backend_(false), | 394 building_backend_(false), |
300 bypass_lock_for_test_(false), | 395 bypass_lock_for_test_(false), |
396 use_stale_while_revalidate_(params.use_stale_while_revalidate), | |
301 mode_(NORMAL), | 397 mode_(NORMAL), |
302 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), | 398 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), |
303 weak_factory_(this) { | 399 weak_factory_(this) { |
304 SetupQuicServerInfoFactory(network_layer_->GetSession()); | 400 SetupQuicServerInfoFactory(network_layer_->GetSession()); |
305 } | 401 } |
306 | 402 |
307 | 403 |
308 // This call doesn't change the shared |session|'s QuicServerInfoFactory because | 404 // This call doesn't change the shared |session|'s QuicServerInfoFactory because |
309 // |session| is shared. | 405 // |session| is shared. |
310 HttpCache::HttpCache(HttpNetworkSession* session, | 406 HttpCache::HttpCache(HttpNetworkSession* session, |
311 BackendFactory* backend_factory) | 407 BackendFactory* backend_factory) |
312 : net_log_(session->net_log()), | 408 : net_log_(session->net_log()), |
313 backend_factory_(backend_factory), | 409 backend_factory_(backend_factory), |
314 building_backend_(false), | 410 building_backend_(false), |
315 bypass_lock_for_test_(false), | 411 bypass_lock_for_test_(false), |
412 use_stale_while_revalidate_(session->params().use_stale_while_revalidate), | |
316 mode_(NORMAL), | 413 mode_(NORMAL), |
317 network_layer_(new HttpNetworkLayer(session)), | 414 network_layer_(new HttpNetworkLayer(session)), |
318 weak_factory_(this) { | 415 weak_factory_(this) { |
319 } | 416 } |
320 | 417 |
321 HttpCache::HttpCache(HttpTransactionFactory* network_layer, | 418 HttpCache::HttpCache(HttpTransactionFactory* network_layer, |
322 NetLog* net_log, | 419 NetLog* net_log, |
323 BackendFactory* backend_factory) | 420 BackendFactory* backend_factory) |
324 : net_log_(net_log), | 421 : net_log_(net_log), |
325 backend_factory_(backend_factory), | 422 backend_factory_(backend_factory), |
326 building_backend_(false), | 423 building_backend_(false), |
327 bypass_lock_for_test_(false), | 424 bypass_lock_for_test_(false), |
425 use_stale_while_revalidate_(false), | |
328 mode_(NORMAL), | 426 mode_(NORMAL), |
329 network_layer_(network_layer), | 427 network_layer_(network_layer), |
330 weak_factory_(this) { | 428 weak_factory_(this) { |
331 SetupQuicServerInfoFactory(network_layer_->GetSession()); | 429 SetupQuicServerInfoFactory(network_layer_->GetSession()); |
430 HttpNetworkSession* session = network_layer_->GetSession(); | |
431 if (session) | |
432 use_stale_while_revalidate_ = session->params().use_stale_while_revalidate; | |
332 } | 433 } |
333 | 434 |
334 HttpCache::~HttpCache() { | 435 HttpCache::~HttpCache() { |
335 // Transactions should see an invalid cache after this point; otherwise they | 436 // Transactions should see an invalid cache after this point; otherwise they |
336 // could see an inconsistent object (half destroyed). | 437 // could see an inconsistent object (half destroyed). |
337 weak_factory_.InvalidateWeakPtrs(); | 438 weak_factory_.InvalidateWeakPtrs(); |
338 | 439 |
339 // If we have any active entries remaining, then we need to deactivate them. | 440 // If we have any active entries remaining, then we need to deactivate them. |
340 // We may have some pending calls to OnProcessPendingQueue, but since those | 441 // We may have some pending calls to OnProcessPendingQueue, but since those |
341 // won't run (due to our destruction), we can simply ignore the corresponding | 442 // won't run (due to our destruction), we can simply ignore the corresponding |
342 // will_process_pending_queue flag. | 443 // will_process_pending_queue flag. |
343 while (!active_entries_.empty()) { | 444 while (!active_entries_.empty()) { |
344 ActiveEntry* entry = active_entries_.begin()->second; | 445 ActiveEntry* entry = active_entries_.begin()->second; |
345 entry->will_process_pending_queue = false; | 446 entry->will_process_pending_queue = false; |
346 entry->pending_queue.clear(); | 447 entry->pending_queue.clear(); |
347 entry->readers.clear(); | 448 entry->readers.clear(); |
348 entry->writer = NULL; | 449 entry->writer = NULL; |
349 DeactivateEntry(entry); | 450 DeactivateEntry(entry); |
350 } | 451 } |
351 | 452 |
352 STLDeleteElements(&doomed_entries_); | 453 STLDeleteElements(&doomed_entries_); |
454 STLDeleteElements(&async_validations_); | |
353 | 455 |
354 // Before deleting pending_ops_, we have to make sure that the disk cache is | 456 // Before deleting pending_ops_, we have to make sure that the disk cache is |
355 // done with said operations, or it will attempt to use deleted data. | 457 // done with said operations, or it will attempt to use deleted data. |
356 cert_cache_.reset(); | 458 cert_cache_.reset(); |
357 disk_cache_.reset(); | 459 disk_cache_.reset(); |
358 | 460 |
359 PendingOpsMap::iterator pending_it = pending_ops_.begin(); | 461 PendingOpsMap::iterator pending_it = pending_ops_.begin(); |
360 for (; pending_it != pending_ops_.end(); ++pending_it) { | 462 for (; pending_it != pending_ops_.end(); ++pending_it) { |
361 // We are not notifying the transactions about the cache going away, even | 463 // We are not notifying the transactions about the cache going away, even |
362 // though they are waiting for a callback that will never fire. | 464 // though they are waiting for a callback that will never fire. |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1031 // not delete the entry before OnProcessPendingQueue runs. | 1133 // not delete the entry before OnProcessPendingQueue runs. |
1032 if (entry->will_process_pending_queue) | 1134 if (entry->will_process_pending_queue) |
1033 return; | 1135 return; |
1034 entry->will_process_pending_queue = true; | 1136 entry->will_process_pending_queue = true; |
1035 | 1137 |
1036 base::MessageLoop::current()->PostTask( | 1138 base::MessageLoop::current()->PostTask( |
1037 FROM_HERE, | 1139 FROM_HERE, |
1038 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); | 1140 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); |
1039 } | 1141 } |
1040 | 1142 |
1143 void HttpCache::PerformAsyncValidation(const HttpRequestInfo& original_request, | |
1144 const BoundNetLog& net_log) { | |
yhirano
2014/08/26 07:52:01
DCHECK(use_stale_while_revalidate_)?
Adam Rice
2014/08/26 13:38:41
Done.
| |
1145 scoped_ptr<AsyncValidation> job(new AsyncValidation(original_request, this)); | |
1146 job->Start(net_log); | |
yhirano
2014/08/26 07:52:01
When all operations are done synchronously, |this-
Adam Rice
2014/08/26 13:38:41
Good catch! Thanks!
I have added a test (Synchron
| |
1147 bool insert_ok = async_validations_.insert(job.release()).second; | |
1148 DCHECK(insert_ok); | |
1149 } | |
1150 | |
1151 void HttpCache::DeleteAsyncValidation(AsyncValidation* async_validation) { | |
1152 size_t erased = async_validations_.erase(async_validation); | |
1153 DCHECK_EQ(1U, erased); | |
1154 delete async_validation; | |
1155 } | |
1156 | |
1041 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { | 1157 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { |
1042 entry->will_process_pending_queue = false; | 1158 entry->will_process_pending_queue = false; |
1043 DCHECK(!entry->writer); | 1159 DCHECK(!entry->writer); |
1044 | 1160 |
1045 // If no one is interested in this entry, then we can deactivate it. | 1161 // If no one is interested in this entry, then we can deactivate it. |
1046 if (entry->pending_queue.empty()) { | 1162 if (entry->pending_queue.empty()) { |
1047 if (entry->readers.empty()) | 1163 if (entry->readers.empty()) |
1048 DestroyEntry(entry); | 1164 DestroyEntry(entry); |
1049 return; | 1165 return; |
1050 } | 1166 } |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 building_backend_ = false; | 1317 building_backend_ = false; |
1202 DeletePendingOp(pending_op); | 1318 DeletePendingOp(pending_op); |
1203 } | 1319 } |
1204 | 1320 |
1205 // The cache may be gone when we return from the callback. | 1321 // The cache may be gone when we return from the callback. |
1206 if (!item->DoCallback(result, disk_cache_.get())) | 1322 if (!item->DoCallback(result, disk_cache_.get())) |
1207 item->NotifyTransaction(result, NULL); | 1323 item->NotifyTransaction(result, NULL); |
1208 } | 1324 } |
1209 | 1325 |
1210 } // namespace net | 1326 } // namespace net |
OLD | NEW |