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

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

Issue 1041763002: Remove stale-while-revalidate experimental implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing header includes. Created 5 years, 6 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
OLDNEW
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/files/file_util.h" 18 #include "base/files/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"
25 #include "base/pickle.h" 24 #include "base/pickle.h"
26 #include "base/stl_util.h" 25 #include "base/stl_util.h"
27 #include "base/strings/string_number_conversions.h" 26 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h" 27 #include "base/strings/string_util.h"
29 #include "base/strings/stringprintf.h" 28 #include "base/strings/stringprintf.h"
30 #include "base/threading/worker_pool.h" 29 #include "base/threading/worker_pool.h"
31 #include "base/time/default_clock.h" 30 #include "base/time/default_clock.h"
32 #include "base/time/time.h" 31 #include "base/time/time.h"
33 #include "net/base/cache_type.h" 32 #include "net/base/cache_type.h"
34 #include "net/base/io_buffer.h" 33 #include "net/base/io_buffer.h"
35 #include "net/base/load_flags.h" 34 #include "net/base/load_flags.h"
36 #include "net/base/net_errors.h" 35 #include "net/base/net_errors.h"
37 #include "net/base/network_delegate.h"
38 #include "net/base/upload_data_stream.h" 36 #include "net/base/upload_data_stream.h"
39 #include "net/disk_cache/disk_cache.h" 37 #include "net/disk_cache/disk_cache.h"
40 #include "net/http/disk_based_cert_cache.h" 38 #include "net/http/disk_based_cert_cache.h"
41 #include "net/http/disk_cache_based_quic_server_info.h" 39 #include "net/http/disk_cache_based_quic_server_info.h"
42 #include "net/http/http_cache_transaction.h" 40 #include "net/http/http_cache_transaction.h"
43 #include "net/http/http_network_layer.h" 41 #include "net/http/http_network_layer.h"
44 #include "net/http/http_network_session.h" 42 #include "net/http/http_network_session.h"
45 #include "net/http/http_request_info.h" 43 #include "net/http/http_request_info.h"
46 #include "net/http/http_response_headers.h" 44 #include "net/http/http_response_headers.h"
47 #include "net/http/http_response_info.h" 45 #include "net/http/http_response_info.h"
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 286
289 QuicServerInfo* GetForServer(const QuicServerId& server_id) override { 287 QuicServerInfo* GetForServer(const QuicServerId& server_id) override {
290 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); 288 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_);
291 } 289 }
292 290
293 private: 291 private:
294 HttpCache* const http_cache_; 292 HttpCache* const http_cache_;
295 }; 293 };
296 294
297 //----------------------------------------------------------------------------- 295 //-----------------------------------------------------------------------------
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,
306 scoped_ptr<Transaction> transaction,
307 NetworkDelegate* network_delegate);
308
309 private:
310 void OnStarted(int result);
311 void DoRead();
312 void OnRead(int result);
313
314 // Terminate this request with net error code |result|. Logs the transaction
315 // result and asks HttpCache to delete this object.
316 // If there was a client or server certificate error, it cannot be recovered
317 // asynchronously, so we need to prevent future attempts to asynchronously
318 // fetch the resource. In this case, the cache entry is doomed.
319 void Terminate(int result);
320
321 HttpRequestInfo request_;
322 scoped_refptr<IOBuffer> buf_;
323 CompletionCallback read_callback_;
324 scoped_ptr<Transaction> transaction_;
325 base::Time start_time_;
326
327 // The HttpCache object owns this object. This object is always deleted before
328 // the pointer to the cache becomes invalid.
329 HttpCache* cache_;
330
331 DISALLOW_COPY_AND_ASSIGN(AsyncValidation);
332 };
333
334 void HttpCache::AsyncValidation::Start(const BoundNetLog& net_log,
335 scoped_ptr<Transaction> transaction,
336 NetworkDelegate* network_delegate) {
337 transaction_ = transaction.Pass();
338 if (network_delegate) {
339 // This code is necessary to enable async transactions to pass over the
340 // data-reduction proxy. This is a violation of the "once-and-only-once"
341 // principle, since it copies code from URLRequestHttpJob. We cannot use the
342 // original callback passed to HttpCache::Transaction by URLRequestHttpJob
343 // as it will only be valid as long as the URLRequestHttpJob object is
344 // alive, and that object will be deleted as soon as the synchronous request
345 // completes.
346 //
347 // This code is also an encapsulation violation. We are exploiting the fact
348 // that the |request| parameter to NotifyBeforeSendProxyHeaders() is never
349 // actually used for anything, and so can be NULL.
350 //
351 // TODO(ricea): Do this better.
352 transaction_->SetBeforeProxyHeadersSentCallback(
353 base::Bind(&NetworkDelegate::NotifyBeforeSendProxyHeaders,
354 base::Unretained(network_delegate),
355 static_cast<URLRequest*>(NULL)));
356 // The above use of base::Unretained is safe because the NetworkDelegate has
357 // to live at least as long as the HttpNetworkSession which has to live as
358 // least as long as the HttpNetworkLayer which has to live at least as long
359 // this HttpCache object.
360 }
361
362 DCHECK_EQ(0, request_.load_flags & LOAD_ASYNC_REVALIDATION);
363 request_.load_flags |= LOAD_ASYNC_REVALIDATION;
364 start_time_ = cache_->clock()->Now();
365 // This use of base::Unretained is safe because |transaction_| is owned by
366 // this object.
367 read_callback_ = base::Bind(&AsyncValidation::OnRead, base::Unretained(this));
368 // This use of base::Unretained is safe as above.
369 int rv = transaction_->Start(
370 &request_,
371 base::Bind(&AsyncValidation::OnStarted, base::Unretained(this)),
372 net_log);
373
374 if (rv == ERR_IO_PENDING)
375 return;
376
377 OnStarted(rv);
378 }
379
380 void HttpCache::AsyncValidation::OnStarted(int result) {
381 if (result != OK) {
382 DVLOG(1) << "Asynchronous transaction start failed for " << request_.url;
383 Terminate(result);
384 return;
385 }
386
387 while (transaction_->IsReadyToRestartForAuth()) {
388 // This code is based on URLRequestHttpJob::RestartTransactionWithAuth,
389 // however when we do this here cookies on the response will not be
390 // stored. Fortunately only a tiny number of sites set cookies on 401
391 // responses, and none of them use stale-while-revalidate.
392 result = transaction_->RestartWithAuth(
393 AuthCredentials(),
394 base::Bind(&AsyncValidation::OnStarted, base::Unretained(this)));
395 if (result == ERR_IO_PENDING)
396 return;
397 if (result != OK) {
398 DVLOG(1) << "Synchronous transaction restart with auth failed for "
399 << request_.url;
400 Terminate(result);
401 return;
402 }
403 }
404
405 DoRead();
406 }
407
408 void HttpCache::AsyncValidation::DoRead() {
409 const size_t kBufSize = 4096;
410 if (!buf_.get())
411 buf_ = new IOBuffer(kBufSize);
412
413 int rv = 0;
414 do {
415 rv = transaction_->Read(buf_.get(), kBufSize, read_callback_);
416 } while (rv > 0);
417
418 if (rv == ERR_IO_PENDING)
419 return;
420
421 OnRead(rv);
422 }
423
424 void HttpCache::AsyncValidation::OnRead(int result) {
425 if (result > 0) {
426 DoRead();
427 return;
428 }
429 Terminate(result);
430 }
431
432 void HttpCache::AsyncValidation::Terminate(int result) {
433 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED || IsCertificateError(result)) {
434 // We should not attempt to access this resource asynchronously again until
435 // the certificate problem has been resolved.
436 // TODO(ricea): For ERR_SSL_CLIENT_AUTH_CERT_NEEDED, mark the entry as
437 // requiring synchronous revalidation rather than just deleting it. Other
438 // certificate errors cause the resource to be considered uncacheable
439 // anyway.
440 cache_->DoomEntry(transaction_->key(), transaction_.get());
441 }
442 base::TimeDelta duration = cache_->clock()->Now() - start_time_;
443 UMA_HISTOGRAM_TIMES("HttpCache.AsyncValidationDuration", duration);
444 transaction_->net_log().EndEventWithNetErrorCode(
445 NetLog::TYPE_ASYNC_REVALIDATION, result);
446 cache_->DeleteAsyncValidation(cache_->GenerateCacheKey(&request_));
447 // |this| is deleted.
448 }
449
450 //-----------------------------------------------------------------------------
451 HttpCache::HttpCache(const HttpNetworkSession::Params& params, 296 HttpCache::HttpCache(const HttpNetworkSession::Params& params,
452 BackendFactory* backend_factory) 297 BackendFactory* backend_factory)
453 : net_log_(params.net_log), 298 : net_log_(params.net_log),
454 backend_factory_(backend_factory), 299 backend_factory_(backend_factory),
455 building_backend_(false), 300 building_backend_(false),
456 bypass_lock_for_test_(false), 301 bypass_lock_for_test_(false),
457 fail_conditionalization_for_test_(false), 302 fail_conditionalization_for_test_(false),
458 use_stale_while_revalidate_(params.use_stale_while_revalidate),
459 mode_(NORMAL), 303 mode_(NORMAL),
460 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), 304 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))),
461 clock_(new base::DefaultClock()), 305 clock_(new base::DefaultClock()),
462 weak_factory_(this) { 306 weak_factory_(this) {
463 SetupQuicServerInfoFactory(network_layer_->GetSession()); 307 SetupQuicServerInfoFactory(network_layer_->GetSession());
464 } 308 }
465 309
466 310
467 // This call doesn't change the shared |session|'s QuicServerInfoFactory because 311 // This call doesn't change the shared |session|'s QuicServerInfoFactory because
468 // |session| is shared. 312 // |session| is shared.
469 HttpCache::HttpCache(HttpNetworkSession* session, 313 HttpCache::HttpCache(HttpNetworkSession* session,
470 BackendFactory* backend_factory) 314 BackendFactory* backend_factory)
471 : net_log_(session->net_log()), 315 : net_log_(session->net_log()),
472 backend_factory_(backend_factory), 316 backend_factory_(backend_factory),
473 building_backend_(false), 317 building_backend_(false),
474 bypass_lock_for_test_(false), 318 bypass_lock_for_test_(false),
475 fail_conditionalization_for_test_(false), 319 fail_conditionalization_for_test_(false),
476 use_stale_while_revalidate_(session->params().use_stale_while_revalidate),
477 mode_(NORMAL), 320 mode_(NORMAL),
478 network_layer_(new HttpNetworkLayer(session)), 321 network_layer_(new HttpNetworkLayer(session)),
479 clock_(new base::DefaultClock()), 322 clock_(new base::DefaultClock()),
480 weak_factory_(this) { 323 weak_factory_(this) {
481 } 324 }
482 325
483 HttpCache::HttpCache(HttpTransactionFactory* network_layer, 326 HttpCache::HttpCache(HttpTransactionFactory* network_layer,
484 NetLog* net_log, 327 NetLog* net_log,
485 BackendFactory* backend_factory) 328 BackendFactory* backend_factory)
486 : net_log_(net_log), 329 : net_log_(net_log),
487 backend_factory_(backend_factory), 330 backend_factory_(backend_factory),
488 building_backend_(false), 331 building_backend_(false),
489 bypass_lock_for_test_(false), 332 bypass_lock_for_test_(false),
490 fail_conditionalization_for_test_(false), 333 fail_conditionalization_for_test_(false),
491 use_stale_while_revalidate_(false),
492 mode_(NORMAL), 334 mode_(NORMAL),
493 network_layer_(network_layer), 335 network_layer_(network_layer),
494 clock_(new base::DefaultClock()), 336 clock_(new base::DefaultClock()),
495 weak_factory_(this) { 337 weak_factory_(this) {
496 SetupQuicServerInfoFactory(network_layer_->GetSession()); 338 SetupQuicServerInfoFactory(network_layer_->GetSession());
497 HttpNetworkSession* session = network_layer_->GetSession();
498 if (session)
499 use_stale_while_revalidate_ = session->params().use_stale_while_revalidate;
500 } 339 }
501 340
502 HttpCache::~HttpCache() { 341 HttpCache::~HttpCache() {
503 // Transactions should see an invalid cache after this point; otherwise they 342 // Transactions should see an invalid cache after this point; otherwise they
504 // could see an inconsistent object (half destroyed). 343 // could see an inconsistent object (half destroyed).
505 weak_factory_.InvalidateWeakPtrs(); 344 weak_factory_.InvalidateWeakPtrs();
506 345
507 // If we have any active entries remaining, then we need to deactivate them. 346 // If we have any active entries remaining, then we need to deactivate them.
508 // We may have some pending calls to OnProcessPendingQueue, but since those 347 // We may have some pending calls to OnProcessPendingQueue, but since those
509 // won't run (due to our destruction), we can simply ignore the corresponding 348 // won't run (due to our destruction), we can simply ignore the corresponding
510 // will_process_pending_queue flag. 349 // will_process_pending_queue flag.
511 while (!active_entries_.empty()) { 350 while (!active_entries_.empty()) {
512 ActiveEntry* entry = active_entries_.begin()->second; 351 ActiveEntry* entry = active_entries_.begin()->second;
513 entry->will_process_pending_queue = false; 352 entry->will_process_pending_queue = false;
514 entry->pending_queue.clear(); 353 entry->pending_queue.clear();
515 entry->readers.clear(); 354 entry->readers.clear();
516 entry->writer = NULL; 355 entry->writer = NULL;
517 DeactivateEntry(entry); 356 DeactivateEntry(entry);
518 } 357 }
519 358
520 STLDeleteElements(&doomed_entries_); 359 STLDeleteElements(&doomed_entries_);
521 STLDeleteValues(&async_validations_);
522 360
523 // Before deleting pending_ops_, we have to make sure that the disk cache is 361 // Before deleting pending_ops_, we have to make sure that the disk cache is
524 // done with said operations, or it will attempt to use deleted data. 362 // done with said operations, or it will attempt to use deleted data.
525 cert_cache_.reset(); 363 cert_cache_.reset();
526 disk_cache_.reset(); 364 disk_cache_.reset();
527 365
528 PendingOpsMap::iterator pending_it = pending_ops_.begin(); 366 PendingOpsMap::iterator pending_it = pending_ops_.begin();
529 for (; pending_it != pending_ops_.end(); ++pending_it) { 367 for (; pending_it != pending_ops_.end(); ++pending_it) {
530 // We are not notifying the transactions about the cache going away, even 368 // We are not notifying the transactions about the cache going away, even
531 // though they are waiting for a callback that will never fire. 369 // though they are waiting for a callback that will never fire.
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 // not delete the entry before OnProcessPendingQueue runs. 1011 // not delete the entry before OnProcessPendingQueue runs.
1174 if (entry->will_process_pending_queue) 1012 if (entry->will_process_pending_queue)
1175 return; 1013 return;
1176 entry->will_process_pending_queue = true; 1014 entry->will_process_pending_queue = true;
1177 1015
1178 base::MessageLoop::current()->PostTask( 1016 base::MessageLoop::current()->PostTask(
1179 FROM_HERE, 1017 FROM_HERE,
1180 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); 1018 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
1181 } 1019 }
1182 1020
1183 void HttpCache::PerformAsyncValidation(const HttpRequestInfo& original_request,
1184 const BoundNetLog& net_log) {
1185 DCHECK(use_stale_while_revalidate_);
1186 std::string key = GenerateCacheKey(&original_request);
1187 AsyncValidation* async_validation =
1188 new AsyncValidation(original_request, this);
1189 typedef AsyncValidationMap::value_type AsyncValidationKeyValue;
1190 bool insert_ok =
1191 async_validations_.insert(AsyncValidationKeyValue(key, async_validation))
1192 .second;
1193 if (!insert_ok) {
1194 DVLOG(1) << "Harmless race condition detected on URL "
1195 << original_request.url << "; discarding redundant revalidation.";
1196 delete async_validation;
1197 return;
1198 }
1199 HttpNetworkSession* network_session = GetSession();
1200 NetworkDelegate* network_delegate = NULL;
1201 if (network_session)
1202 network_delegate = network_session->network_delegate();
1203 scoped_ptr<HttpTransaction> transaction;
1204 CreateTransaction(IDLE, &transaction);
1205 scoped_ptr<Transaction> downcast_transaction(
1206 static_cast<Transaction*>(transaction.release()));
1207 async_validation->Start(
1208 net_log, downcast_transaction.Pass(), network_delegate);
1209 // |async_validation| may have been deleted here.
1210 }
1211
1212 void HttpCache::DeleteAsyncValidation(const std::string& url) {
1213 AsyncValidationMap::iterator it = async_validations_.find(url);
1214 CHECK(it != async_validations_.end()); // security-critical invariant
1215 AsyncValidation* async_validation = it->second;
1216 async_validations_.erase(it);
1217 delete async_validation;
1218 }
1219
1220 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { 1021 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
1221 entry->will_process_pending_queue = false; 1022 entry->will_process_pending_queue = false;
1222 DCHECK(!entry->writer); 1023 DCHECK(!entry->writer);
1223 1024
1224 // If no one is interested in this entry, then we can deactivate it. 1025 // If no one is interested in this entry, then we can deactivate it.
1225 if (entry->pending_queue.empty()) { 1026 if (entry->pending_queue.empty()) {
1226 if (entry->readers.empty()) 1027 if (entry->readers.empty())
1227 DestroyEntry(entry); 1028 DestroyEntry(entry);
1228 return; 1029 return;
1229 } 1030 }
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 building_backend_ = false; 1181 building_backend_ = false;
1381 DeletePendingOp(pending_op); 1182 DeletePendingOp(pending_op);
1382 } 1183 }
1383 1184
1384 // The cache may be gone when we return from the callback. 1185 // The cache may be gone when we return from the callback.
1385 if (!item->DoCallback(result, disk_cache_.get())) 1186 if (!item->DoCallback(result, disk_cache_.get()))
1386 item->NotifyTransaction(result, NULL); 1187 item->NotifyTransaction(result, NULL);
1387 } 1188 }
1388 1189
1389 } // namespace net 1190 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698