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 |
11 #if defined(OS_POSIX) | 11 #if defined(OS_POSIX) |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 #endif | 13 #endif |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/bind_helpers.h" | 16 #include "base/bind_helpers.h" |
17 #include "base/callback.h" | 17 #include "base/callback.h" |
18 #include "base/file_util.h" | 18 #include "base/file_util.h" |
19 #include "base/format_macros.h" | 19 #include "base/format_macros.h" |
20 #include "base/location.h" | 20 #include "base/location.h" |
21 #include "base/memory/ref_counted.h" | 21 #include "base/memory/ref_counted.h" |
22 #include "base/message_loop/message_loop.h" | 22 #include "base/message_loop/message_loop.h" |
23 #include "base/metrics/field_trial.h" | 23 #include "base/metrics/field_trial.h" |
24 #include "base/metrics/histogram.h" | |
24 #include "base/pickle.h" | 25 #include "base/pickle.h" |
25 #include "base/stl_util.h" | 26 #include "base/stl_util.h" |
26 #include "base/strings/string_number_conversions.h" | 27 #include "base/strings/string_number_conversions.h" |
27 #include "base/strings/string_util.h" | 28 #include "base/strings/string_util.h" |
28 #include "base/strings/stringprintf.h" | 29 #include "base/strings/stringprintf.h" |
29 #include "base/threading/worker_pool.h" | 30 #include "base/threading/worker_pool.h" |
31 #include "base/time/time.h" | |
30 #include "net/base/cache_type.h" | 32 #include "net/base/cache_type.h" |
31 #include "net/base/io_buffer.h" | 33 #include "net/base/io_buffer.h" |
32 #include "net/base/load_flags.h" | 34 #include "net/base/load_flags.h" |
33 #include "net/base/net_errors.h" | 35 #include "net/base/net_errors.h" |
36 #include "net/base/network_delegate.h" | |
34 #include "net/base/upload_data_stream.h" | 37 #include "net/base/upload_data_stream.h" |
35 #include "net/disk_cache/disk_cache.h" | 38 #include "net/disk_cache/disk_cache.h" |
36 #include "net/http/disk_based_cert_cache.h" | 39 #include "net/http/disk_based_cert_cache.h" |
37 #include "net/http/disk_cache_based_quic_server_info.h" | 40 #include "net/http/disk_cache_based_quic_server_info.h" |
38 #include "net/http/http_cache_transaction.h" | 41 #include "net/http/http_cache_transaction.h" |
39 #include "net/http/http_network_layer.h" | 42 #include "net/http/http_network_layer.h" |
40 #include "net/http/http_network_session.h" | 43 #include "net/http/http_network_session.h" |
41 #include "net/http/http_request_info.h" | 44 #include "net/http/http_request_info.h" |
42 #include "net/http/http_response_headers.h" | 45 #include "net/http/http_response_headers.h" |
43 #include "net/http/http_response_info.h" | 46 #include "net/http/http_response_info.h" |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 virtual QuicServerInfo* GetForServer( | 288 virtual QuicServerInfo* GetForServer( |
286 const QuicServerId& server_id) OVERRIDE { | 289 const QuicServerId& server_id) OVERRIDE { |
287 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); | 290 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); |
288 } | 291 } |
289 | 292 |
290 private: | 293 private: |
291 HttpCache* const http_cache_; | 294 HttpCache* const http_cache_; |
292 }; | 295 }; |
293 | 296 |
294 //----------------------------------------------------------------------------- | 297 //----------------------------------------------------------------------------- |
298 | |
299 class HttpCache::AsyncValidation { | |
300 public: | |
301 AsyncValidation(const HttpRequestInfo& original_request, HttpCache* cache) | |
302 : request_(original_request), cache_(cache) {} | |
303 ~AsyncValidation() {} | |
304 | |
305 void Start(const BoundNetLog& net_log, NetworkDelegate* network_delegate); | |
306 | |
307 private: | |
308 void OnStarted(int result); | |
309 void DoRead(); | |
310 void OnRead(int result); | |
311 | |
312 // Terminate this request with net error code |result|. Logs the transaction | |
313 // result and asks HttpCache to delete this object. | |
314 // If there was a client or server certificate error, it cannot be recovered | |
315 // asynchronously, so we need to prevent futures attempts to asynchronously | |
316 // fetch the resource. In this case, the cache entry is doomed. | |
317 void Terminate(int result); | |
318 | |
319 HttpRequestInfo request_; | |
320 scoped_refptr<IOBuffer> buf_; | |
321 CompletionCallback read_callback_; | |
322 scoped_ptr<Transaction> transaction_; | |
323 base::Time start_time_; | |
324 | |
325 // The HttpCache object owns this object. This object is always deleted before | |
326 // the pointer to the cache becomes invalid. | |
327 HttpCache* cache_; | |
328 | |
329 DISALLOW_COPY_AND_ASSIGN(AsyncValidation); | |
330 }; | |
331 | |
332 void HttpCache::AsyncValidation::Start(const BoundNetLog& net_log, | |
333 NetworkDelegate* network_delegate) { | |
334 transaction_.reset(new Transaction(IDLE, cache_)); | |
335 if (network_delegate) { | |
yhirano
2014/08/27 09:24:29
Can you pass before_proxy_headers_sent_callback_ f
Adam Rice
2014/08/28 03:14:35
That callback is only valid for the lifetime of th
| |
336 // This code is necessary to enable async transactions to pass over the | |
337 // data-reduction proxy. This is a violation of the "once-and-only-once" | |
338 // principle, since it copies code from URLRequestHttpJob. It also may be an | |
339 // encapsulation violation. We are also exploiting the fact that the | |
340 // |request| parameter to NotifyBeforeSendProxyHeaders() is never actually | |
341 // used for anything, and so can be NULL. | |
342 // TODO(ricea): Do this better. | |
343 transaction_->SetBeforeProxyHeadersSentCallback( | |
344 base::Bind(&NetworkDelegate::NotifyBeforeSendProxyHeaders, | |
345 base::Unretained(network_delegate), | |
346 static_cast<URLRequest*>(NULL))); | |
347 // The above use of base::Unretained is safe because the NetworkDelegate has | |
348 // to live at least as long as the HttpNetworkSession which has to live as | |
349 // least as long as the HttpNetworkLayer which has to live at least as long | |
350 // this HttpCache object. | |
351 } | |
352 | |
353 request_.load_flags |= LOAD_VALIDATE_CACHE; | |
354 start_time_ = base::Time::Now(); | |
355 // This use of base::Unretained is safe because |transaction_| is owned by | |
356 // this object. | |
357 read_callback_ = base::Bind(&AsyncValidation::OnRead, base::Unretained(this)); | |
358 // This use of base::Unretained is safe as above. | |
359 int rv = transaction_->Start( | |
360 &request_, | |
361 base::Bind(&AsyncValidation::OnStarted, base::Unretained(this)), | |
362 net_log); | |
363 | |
364 if (rv == ERR_IO_PENDING) | |
365 return; | |
366 | |
367 OnStarted(rv); | |
368 } | |
369 | |
370 void HttpCache::AsyncValidation::OnStarted(int result) { | |
371 if (result != OK) { | |
372 DVLOG(1) << "Asynchronous transaction start failed for " << request_.url; | |
373 Terminate(result); | |
374 return; | |
375 } | |
376 | |
377 DoRead(); | |
378 } | |
379 | |
380 void HttpCache::AsyncValidation::DoRead() { | |
381 const size_t kBufSize = 4096; | |
382 if (!buf_) | |
383 buf_ = new IOBuffer(kBufSize); | |
384 | |
385 int rv = 0; | |
386 do { | |
387 rv = transaction_->Read(buf_.get(), kBufSize, read_callback_); | |
388 } while (rv > 0); | |
389 | |
390 if (rv == ERR_IO_PENDING) | |
391 return; | |
392 | |
393 OnRead(rv); | |
394 } | |
395 | |
396 void HttpCache::AsyncValidation::OnRead(int result) { | |
397 if (result > 0) { | |
398 DoRead(); | |
399 return; | |
400 } | |
401 Terminate(result); | |
402 } | |
403 | |
404 void HttpCache::AsyncValidation::Terminate(int result) { | |
405 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED || IsCertificateError(result)) | |
406 cache_->DoomEntry(transaction_->key(), transaction_.get()); | |
407 base::TimeDelta time_saved = base::Time::Now() - start_time_; | |
408 UMA_HISTOGRAM_TIMES("HttpCache.AsyncValidationTimeSaved", time_saved); | |
409 transaction_->net_log().EndEventWithNetErrorCode( | |
410 NetLog::TYPE_ASYNC_REVALIDATION, result); | |
411 cache_->DeleteAsyncValidation(this); | |
412 // |this| is deleted. | |
413 } | |
414 | |
415 //----------------------------------------------------------------------------- | |
295 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, | 416 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, |
296 BackendFactory* backend_factory) | 417 BackendFactory* backend_factory) |
297 : net_log_(params.net_log), | 418 : net_log_(params.net_log), |
298 backend_factory_(backend_factory), | 419 backend_factory_(backend_factory), |
299 building_backend_(false), | 420 building_backend_(false), |
300 bypass_lock_for_test_(false), | 421 bypass_lock_for_test_(false), |
422 use_stale_while_revalidate_(params.use_stale_while_revalidate), | |
301 mode_(NORMAL), | 423 mode_(NORMAL), |
302 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), | 424 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), |
303 weak_factory_(this) { | 425 weak_factory_(this) { |
304 SetupQuicServerInfoFactory(network_layer_->GetSession()); | 426 SetupQuicServerInfoFactory(network_layer_->GetSession()); |
305 } | 427 } |
306 | 428 |
307 | 429 |
308 // This call doesn't change the shared |session|'s QuicServerInfoFactory because | 430 // This call doesn't change the shared |session|'s QuicServerInfoFactory because |
309 // |session| is shared. | 431 // |session| is shared. |
310 HttpCache::HttpCache(HttpNetworkSession* session, | 432 HttpCache::HttpCache(HttpNetworkSession* session, |
311 BackendFactory* backend_factory) | 433 BackendFactory* backend_factory) |
312 : net_log_(session->net_log()), | 434 : net_log_(session->net_log()), |
313 backend_factory_(backend_factory), | 435 backend_factory_(backend_factory), |
314 building_backend_(false), | 436 building_backend_(false), |
315 bypass_lock_for_test_(false), | 437 bypass_lock_for_test_(false), |
438 use_stale_while_revalidate_(session->params().use_stale_while_revalidate), | |
316 mode_(NORMAL), | 439 mode_(NORMAL), |
317 network_layer_(new HttpNetworkLayer(session)), | 440 network_layer_(new HttpNetworkLayer(session)), |
318 weak_factory_(this) { | 441 weak_factory_(this) { |
319 } | 442 } |
320 | 443 |
321 HttpCache::HttpCache(HttpTransactionFactory* network_layer, | 444 HttpCache::HttpCache(HttpTransactionFactory* network_layer, |
322 NetLog* net_log, | 445 NetLog* net_log, |
323 BackendFactory* backend_factory) | 446 BackendFactory* backend_factory) |
324 : net_log_(net_log), | 447 : net_log_(net_log), |
325 backend_factory_(backend_factory), | 448 backend_factory_(backend_factory), |
326 building_backend_(false), | 449 building_backend_(false), |
327 bypass_lock_for_test_(false), | 450 bypass_lock_for_test_(false), |
451 use_stale_while_revalidate_(false), | |
328 mode_(NORMAL), | 452 mode_(NORMAL), |
329 network_layer_(network_layer), | 453 network_layer_(network_layer), |
330 weak_factory_(this) { | 454 weak_factory_(this) { |
331 SetupQuicServerInfoFactory(network_layer_->GetSession()); | 455 SetupQuicServerInfoFactory(network_layer_->GetSession()); |
456 HttpNetworkSession* session = network_layer_->GetSession(); | |
457 if (session) | |
458 use_stale_while_revalidate_ = session->params().use_stale_while_revalidate; | |
332 } | 459 } |
333 | 460 |
334 HttpCache::~HttpCache() { | 461 HttpCache::~HttpCache() { |
335 // Transactions should see an invalid cache after this point; otherwise they | 462 // Transactions should see an invalid cache after this point; otherwise they |
336 // could see an inconsistent object (half destroyed). | 463 // could see an inconsistent object (half destroyed). |
337 weak_factory_.InvalidateWeakPtrs(); | 464 weak_factory_.InvalidateWeakPtrs(); |
338 | 465 |
339 // If we have any active entries remaining, then we need to deactivate them. | 466 // 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 | 467 // 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 | 468 // won't run (due to our destruction), we can simply ignore the corresponding |
342 // will_process_pending_queue flag. | 469 // will_process_pending_queue flag. |
343 while (!active_entries_.empty()) { | 470 while (!active_entries_.empty()) { |
344 ActiveEntry* entry = active_entries_.begin()->second; | 471 ActiveEntry* entry = active_entries_.begin()->second; |
345 entry->will_process_pending_queue = false; | 472 entry->will_process_pending_queue = false; |
346 entry->pending_queue.clear(); | 473 entry->pending_queue.clear(); |
347 entry->readers.clear(); | 474 entry->readers.clear(); |
348 entry->writer = NULL; | 475 entry->writer = NULL; |
349 DeactivateEntry(entry); | 476 DeactivateEntry(entry); |
350 } | 477 } |
351 | 478 |
352 STLDeleteElements(&doomed_entries_); | 479 STLDeleteElements(&doomed_entries_); |
480 STLDeleteElements(&async_validations_); | |
353 | 481 |
354 // Before deleting pending_ops_, we have to make sure that the disk cache is | 482 // 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. | 483 // done with said operations, or it will attempt to use deleted data. |
356 cert_cache_.reset(); | 484 cert_cache_.reset(); |
357 disk_cache_.reset(); | 485 disk_cache_.reset(); |
358 | 486 |
359 PendingOpsMap::iterator pending_it = pending_ops_.begin(); | 487 PendingOpsMap::iterator pending_it = pending_ops_.begin(); |
360 for (; pending_it != pending_ops_.end(); ++pending_it) { | 488 for (; pending_it != pending_ops_.end(); ++pending_it) { |
361 // We are not notifying the transactions about the cache going away, even | 489 // We are not notifying the transactions about the cache going away, even |
362 // though they are waiting for a callback that will never fire. | 490 // 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. | 1159 // not delete the entry before OnProcessPendingQueue runs. |
1032 if (entry->will_process_pending_queue) | 1160 if (entry->will_process_pending_queue) |
1033 return; | 1161 return; |
1034 entry->will_process_pending_queue = true; | 1162 entry->will_process_pending_queue = true; |
1035 | 1163 |
1036 base::MessageLoop::current()->PostTask( | 1164 base::MessageLoop::current()->PostTask( |
1037 FROM_HERE, | 1165 FROM_HERE, |
1038 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); | 1166 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); |
1039 } | 1167 } |
1040 | 1168 |
1169 void HttpCache::PerformAsyncValidation(const HttpRequestInfo& original_request, | |
1170 const BoundNetLog& net_log) { | |
1171 DCHECK(use_stale_while_revalidate_); | |
1172 AsyncValidation* job = new AsyncValidation(original_request, this); | |
1173 bool insert_ok = async_validations_.insert(job).second; | |
1174 DCHECK(insert_ok); | |
1175 HttpNetworkSession* network_session = GetSession(); | |
1176 NetworkDelegate* network_delegate = NULL; | |
1177 if (network_session) | |
1178 network_delegate = network_session->network_delegate(); | |
1179 job->Start(net_log, network_delegate); | |
1180 // |job| may have been deleted here. | |
1181 } | |
1182 | |
1183 void HttpCache::DeleteAsyncValidation(AsyncValidation* async_validation) { | |
1184 size_t erased = async_validations_.erase(async_validation); | |
1185 DCHECK_EQ(1U, erased); | |
1186 delete async_validation; | |
1187 } | |
1188 | |
1041 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { | 1189 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { |
1042 entry->will_process_pending_queue = false; | 1190 entry->will_process_pending_queue = false; |
1043 DCHECK(!entry->writer); | 1191 DCHECK(!entry->writer); |
1044 | 1192 |
1045 // If no one is interested in this entry, then we can deactivate it. | 1193 // If no one is interested in this entry, then we can deactivate it. |
1046 if (entry->pending_queue.empty()) { | 1194 if (entry->pending_queue.empty()) { |
1047 if (entry->readers.empty()) | 1195 if (entry->readers.empty()) |
1048 DestroyEntry(entry); | 1196 DestroyEntry(entry); |
1049 return; | 1197 return; |
1050 } | 1198 } |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 building_backend_ = false; | 1349 building_backend_ = false; |
1202 DeletePendingOp(pending_op); | 1350 DeletePendingOp(pending_op); |
1203 } | 1351 } |
1204 | 1352 |
1205 // The cache may be gone when we return from the callback. | 1353 // The cache may be gone when we return from the callback. |
1206 if (!item->DoCallback(result, disk_cache_.get())) | 1354 if (!item->DoCallback(result, disk_cache_.get())) |
1207 item->NotifyTransaction(result, NULL); | 1355 item->NotifyTransaction(result, NULL); |
1208 } | 1356 } |
1209 | 1357 |
1210 } // namespace net | 1358 } // namespace net |
OLD | NEW |