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

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

Issue 1230113012: [net] Better StopCaching() handling for HttpCache::Transaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing MockTransaction initializers Created 5 years, 3 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_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" // For OS_POSIX 7 #include "build/build_config.h" // For OS_POSIX
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 reading_(false), 259 reading_(false),
260 invalid_range_(false), 260 invalid_range_(false),
261 truncated_(false), 261 truncated_(false),
262 is_sparse_(false), 262 is_sparse_(false),
263 range_requested_(false), 263 range_requested_(false),
264 handling_206_(false), 264 handling_206_(false),
265 cache_pending_(false), 265 cache_pending_(false),
266 done_reading_(false), 266 done_reading_(false),
267 vary_mismatch_(false), 267 vary_mismatch_(false),
268 couldnt_conditionalize_request_(false), 268 couldnt_conditionalize_request_(false),
269 stopped_caching_(false),
269 bypass_lock_for_test_(false), 270 bypass_lock_for_test_(false),
270 fail_conditionalization_for_test_(false), 271 fail_conditionalization_for_test_(false),
272 read_buf_len_(0),
271 io_buf_len_(0), 273 io_buf_len_(0),
272 read_offset_(0), 274 read_offset_(0),
273 effective_load_flags_(0), 275 effective_load_flags_(0),
274 write_len_(0), 276 write_len_(0),
275 transaction_pattern_(PATTERN_UNDEFINED), 277 transaction_pattern_(PATTERN_UNDEFINED),
276 total_received_bytes_(0), 278 total_received_bytes_(0),
277 total_sent_bytes_(0), 279 total_sent_bytes_(0),
278 websocket_handshake_stream_base_create_helper_(NULL), 280 websocket_handshake_stream_base_create_helper_(NULL),
279 weak_factory_(this) { 281 weak_factory_(this) {
280 static_assert(HttpCache::Transaction::kNumValidationHeaders == 282 static_assert(HttpCache::Transaction::kNumValidationHeaders ==
281 arraysize(kValidationHeaders), 283 arraysize(kValidationHeaders),
282 "invalid number of validation headers"); 284 "invalid number of validation headers");
283 285
284 io_callback_ = base::Bind(&Transaction::OnIOComplete, 286 io_callback_ = base::Bind(&Transaction::OnIOComplete,
285 weak_factory_.GetWeakPtr()); 287 weak_factory_.GetWeakPtr());
286 } 288 }
287 289
288 HttpCache::Transaction::~Transaction() { 290 HttpCache::Transaction::~Transaction() {
289 // We may have to issue another IO, but we should never invoke the callback_ 291 // We may have to issue another IO, but we should never invoke the callback_
290 // after this point. 292 // after this point.
291 callback_.Reset(); 293 callback_.Reset();
292 294
293 if (cache_) { 295 RecordHistograms();
294 if (entry_) {
295 bool cancel_request = reading_ && response_.headers.get();
296 if (cancel_request) {
297 if (partial_) {
298 entry_->disk_entry->CancelSparseIO();
299 } else {
300 cancel_request &= (response_.headers->response_code() == 200);
301 }
302 }
303 296
304 cache_->DoneWithEntry(entry_, this, cancel_request); 297 if (!cache_)
305 } else if (cache_pending_) { 298 return;
299
300 if (!entry_) {
301 if (cache_pending_)
306 cache_->RemovePendingTransaction(this); 302 cache_->RemovePendingTransaction(this);
307 } 303 return;
308 } 304 }
305
306 bool cancel_request = reading_ && response_.headers.get() &&
307 (response_.headers->response_code() == 200 || partial_);
308 if (cancel_request) {
309 if (partial_)
310 entry_->disk_entry->CancelSparseIO();
311
312 AbandonCacheEntry(CompletionCallback());
313 return;
314 }
315
316 ReleaseCacheEntry(EntryState::DOOM);
309 } 317 }
310 318
311 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 319 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
312 const CompletionCallback& callback) { 320 const CompletionCallback& callback) {
313 DCHECK(buf); 321 DCHECK(buf);
314 DCHECK_GT(buf_len, 0); 322 DCHECK_GT(buf_len, 0);
315 DCHECK(!callback.is_null()); 323 DCHECK(!callback.is_null());
316 if (!cache_.get() || !entry_) 324 if (!cache_.get() || !entry_)
317 return ERR_UNEXPECTED; 325 return ERR_UNEXPECTED;
318 326
319 // We don't need to track this operation for anything. 327 // We don't need to track this operation for anything.
320 // It could be possible to check if there is something already written and 328 // It could be possible to check if there is something already written and
321 // avoid writing again (it should be the same, right?), but let's allow the 329 // avoid writing again (it should be the same, right?), but let's allow the
322 // caller to "update" the contents with something new. 330 // caller to "update" the contents with something new.
323 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 331 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
324 callback, true); 332 callback, true);
325 } 333 }
326 334
327 bool HttpCache::Transaction::AddTruncatedFlag() {
328 DCHECK(mode_ & WRITE || mode_ == NONE);
329
330 // Don't set the flag for sparse entries.
331 if (partial_ && !truncated_)
332 return true;
333
334 if (!CanResume(true))
335 return false;
336
337 // We may have received the whole resource already.
338 if (done_reading_)
339 return true;
340
341 truncated_ = true;
342 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
343 DoLoop(OK);
344 return true;
345 }
346
347 LoadState HttpCache::Transaction::GetWriterLoadState() const { 335 LoadState HttpCache::Transaction::GetWriterLoadState() const {
348 if (network_trans_.get()) 336 if (network_trans_.get())
349 return network_trans_->GetLoadState(); 337 return network_trans_->GetLoadState();
350 if (entry_ || !request_) 338 if (entry_ || !request_)
351 return LOAD_STATE_IDLE; 339 return LOAD_STATE_IDLE;
352 return LOAD_STATE_WAITING_FOR_CACHE; 340 return LOAD_STATE_WAITING_FOR_CACHE;
353 } 341 }
354 342
355 const BoundNetLog& HttpCache::Transaction::net_log() const { 343 const BoundNetLog& HttpCache::Transaction::net_log() const {
356 return net_log_; 344 return net_log_;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 return false; 439 return false;
452 return network_trans_->IsReadyToRestartForAuth(); 440 return network_trans_->IsReadyToRestartForAuth();
453 } 441 }
454 442
455 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 443 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
456 const CompletionCallback& callback) { 444 const CompletionCallback& callback) {
457 DCHECK_EQ(next_state_, STATE_NONE); 445 DCHECK_EQ(next_state_, STATE_NONE);
458 DCHECK(buf); 446 DCHECK(buf);
459 DCHECK_GT(buf_len, 0); 447 DCHECK_GT(buf_len, 0);
460 DCHECK(!callback.is_null()); 448 DCHECK(!callback.is_null());
461
462 DCHECK(callback_.is_null()); 449 DCHECK(callback_.is_null());
463 450
464 if (!cache_.get()) 451 if (!cache_.get())
465 return ERR_UNEXPECTED; 452 return ERR_UNEXPECTED;
466 453
467 // If we have an intermediate auth response at this point, then it means the 454 // If we have an intermediate auth response at this point, then it means the
468 // user wishes to read the network response (the error page). If there is a 455 // user wishes to read the network response (the error page). If there is a
469 // previous response in the cache then we should leave it intact. 456 // previous response in the cache then we should leave it intact.
470 if (auth_response_.headers.get() && mode_ != NONE) { 457 if (auth_response_.headers.get() && mode_ != NONE) {
471 UpdateTransactionPattern(PATTERN_NOT_COVERED); 458 UpdateTransactionPattern(PATTERN_NOT_COVERED);
472 DCHECK(mode_ & WRITE); 459 DCHECK(mode_ & WRITE);
473 DoneWritingToEntry(mode_ == READ_WRITE); 460 ReleaseCacheEntry(mode_ == READ_WRITE ? EntryState::KEEP
474 mode_ = NONE; 461 : EntryState::DOOM);
475 } 462 }
476 463
477 reading_ = true; 464 reading_ = true;
478 read_buf_ = buf; 465 read_buf_ = buf;
479 io_buf_len_ = buf_len; 466 read_buf_len_ = buf_len;
480 if (network_trans_) { 467 if (stopped_caching_ && entry_) {
468 DCHECK(mode_ & WRITE);
469 next_state_ = STATE_SWITCH_TO_NETWORK;
470 } else if (network_trans_) {
481 DCHECK(mode_ == WRITE || mode_ == NONE || 471 DCHECK(mode_ == WRITE || mode_ == NONE ||
482 (mode_ == READ_WRITE && partial_)); 472 (mode_ == READ_WRITE && partial_));
483 next_state_ = STATE_NETWORK_READ; 473 next_state_ = STATE_NETWORK_READ;
484 } else { 474 } else {
485 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); 475 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
486 next_state_ = STATE_CACHE_READ_DATA; 476 next_state_ = STATE_CACHE_READ_DATA;
487 } 477 }
488 478
489 int rv = DoLoop(OK); 479 int rv = DoLoop(OK);
490 480
491 if (rv == ERR_IO_PENDING) { 481 if (rv == ERR_IO_PENDING) {
492 DCHECK(callback_.is_null()); 482 DCHECK(callback_.is_null());
493 callback_ = callback; 483 callback_ = callback;
494 } 484 }
495 return rv; 485 return rv;
496 } 486 }
497 487
498 void HttpCache::Transaction::StopCaching() { 488 void HttpCache::Transaction::StopCaching() {
499 // We really don't know where we are now. Hopefully there is no operation in 489 DCHECK(callback_.is_null());
500 // progress, but nothing really prevents this method to be called after we 490 DCHECK(request_);
501 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this 491
502 // point because we need the state machine for that (and even if we are really 492 // StopCaching requires being able to restart partial network requests. Doing
503 // free, that would be an asynchronous operation). In other words, keep the 493 // so is only reliable if the request is idempotent. In addition, StopCaching
504 // entry how it is (it will be marked as truncated at destruction), and let 494 // is only effective if the transaction is writing to the cache.
505 // the next piece of code that executes know that we are now reading directly 495 if ((!partial_ || request_->method == "GET") && (mode_ & WRITE))
506 // from the net. 496 stopped_caching_ = true;
rvargas (doing something else) 2015/09/21 22:06:00 It looks like we set the flag when method != GET.
507 // TODO(mmenke): This doesn't release the lock on the cache entry, so a
508 // future request for the resource will be blocked on this one.
509 // Fix this.
510 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
511 !is_sparse_ && !range_requested_) {
512 mode_ = NONE;
513 }
514 } 497 }
515 498
516 bool HttpCache::Transaction::GetFullRequestHeaders( 499 bool HttpCache::Transaction::GetFullRequestHeaders(
517 HttpRequestHeaders* headers) const { 500 HttpRequestHeaders* headers) const {
518 if (network_trans_) 501 if (network_trans_)
519 return network_trans_->GetFullRequestHeaders(headers); 502 return network_trans_->GetFullRequestHeaders(headers);
520 503
521 // TODO(ttuttle): Read headers from cache. 504 // TODO(ttuttle): Read headers from cache.
522 return false; 505 return false;
523 } 506 }
524 507
525 int64 HttpCache::Transaction::GetTotalReceivedBytes() const { 508 int64 HttpCache::Transaction::GetTotalReceivedBytes() const {
526 int64 total_received_bytes = total_received_bytes_; 509 int64 total_received_bytes = total_received_bytes_;
527 if (network_trans_) 510 if (network_trans_)
528 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 511 total_received_bytes += network_trans_->GetTotalReceivedBytes();
529 return total_received_bytes; 512 return total_received_bytes;
530 } 513 }
531 514
532 int64_t HttpCache::Transaction::GetTotalSentBytes() const { 515 int64_t HttpCache::Transaction::GetTotalSentBytes() const {
533 int64_t total_sent_bytes = total_sent_bytes_; 516 int64_t total_sent_bytes = total_sent_bytes_;
534 if (network_trans_) 517 if (network_trans_)
535 total_sent_bytes += network_trans_->GetTotalSentBytes(); 518 total_sent_bytes += network_trans_->GetTotalSentBytes();
536 return total_sent_bytes; 519 return total_sent_bytes;
537 } 520 }
538 521
539 void HttpCache::Transaction::DoneReading() { 522 void HttpCache::Transaction::DoneReading() {
540 if (cache_.get() && entry_) { 523 DCHECK_NE(mode_, UPDATE);
541 DCHECK_NE(mode_, UPDATE); 524 if (!cache_ || !entry_)
542 if (mode_ & WRITE) { 525 return;
543 DoneWritingToEntry(true); 526 done_reading_ = true;
544 } else if (mode_ & READ) { 527 ReleaseCacheEntry(EntryState::KEEP);
545 // It is necessary to check mode_ & READ because it is possible
546 // for mode_ to be NONE and entry_ non-NULL with a write entry
547 // if StopCaching was called.
548 cache_->DoneReadingFromEntry(entry_, this);
549 entry_ = NULL;
550 }
551 }
552 } 528 }
553 529
554 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const { 530 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
555 // Null headers means we encountered an error or haven't a response yet 531 // Null headers means we encountered an error or haven't a response yet
556 if (auth_response_.headers.get()) 532 if (auth_response_.headers.get())
557 return &auth_response_; 533 return &auth_response_;
558 return &response_; 534 return &response_;
559 } 535 }
560 536
561 LoadState HttpCache::Transaction::GetLoadState() const { 537 LoadState HttpCache::Transaction::GetLoadState() const {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 DCHECK_EQ(OK, rv); 879 DCHECK_EQ(OK, rv);
904 rv = DoPartialHeadersReceived(); 880 rv = DoPartialHeadersReceived();
905 break; 881 break;
906 case STATE_CACHE_READ_METADATA: 882 case STATE_CACHE_READ_METADATA:
907 DCHECK_EQ(OK, rv); 883 DCHECK_EQ(OK, rv);
908 rv = DoCacheReadMetadata(); 884 rv = DoCacheReadMetadata();
909 break; 885 break;
910 case STATE_CACHE_READ_METADATA_COMPLETE: 886 case STATE_CACHE_READ_METADATA_COMPLETE:
911 rv = DoCacheReadMetadataComplete(rv); 887 rv = DoCacheReadMetadataComplete(rv);
912 break; 888 break;
889 case STATE_SWITCH_TO_NETWORK:
890 rv = DoSwitchToNetwork();
891 break;
913 case STATE_NETWORK_READ: 892 case STATE_NETWORK_READ:
914 DCHECK_EQ(OK, rv); 893 DCHECK_EQ(OK, rv);
915 rv = DoNetworkRead(); 894 rv = DoNetworkRead();
916 break; 895 break;
917 case STATE_NETWORK_READ_COMPLETE: 896 case STATE_NETWORK_READ_COMPLETE:
918 rv = DoNetworkReadComplete(rv); 897 rv = DoNetworkReadComplete(rv);
919 break; 898 break;
920 case STATE_CACHE_READ_DATA: 899 case STATE_CACHE_READ_DATA:
921 DCHECK_EQ(OK, rv); 900 DCHECK_EQ(OK, rv);
922 rv = DoCacheReadData(); 901 rv = DoCacheReadData();
923 break; 902 break;
924 case STATE_CACHE_READ_DATA_COMPLETE: 903 case STATE_CACHE_READ_DATA_COMPLETE:
925 rv = DoCacheReadDataComplete(rv); 904 rv = DoCacheReadDataComplete(rv);
926 break; 905 break;
927 case STATE_CACHE_WRITE_DATA: 906 case STATE_CACHE_WRITE_DATA:
928 rv = DoCacheWriteData(rv); 907 rv = DoCacheWriteData(rv);
929 break; 908 break;
930 case STATE_CACHE_WRITE_DATA_COMPLETE: 909 case STATE_CACHE_WRITE_DATA_COMPLETE:
931 rv = DoCacheWriteDataComplete(rv); 910 rv = DoCacheWriteDataComplete(rv);
932 break; 911 break;
933 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
934 DCHECK_EQ(OK, rv);
935 rv = DoCacheWriteTruncatedResponse();
936 break;
937 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
938 rv = DoCacheWriteTruncatedResponseComplete(rv);
939 break;
940 default: 912 default:
941 NOTREACHED() << "bad state"; 913 NOTREACHED() << "bad state";
942 rv = ERR_FAILED; 914 rv = ERR_FAILED;
943 break; 915 break;
944 } 916 }
945 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 917 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
946 918
947 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 919 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
948 read_buf_ = NULL; // Release the buffer before invoking the callback. 920 read_buf_ = nullptr; // Release the buffer before invoking the callback.
921 read_buf_len_ = 0;
949 base::ResetAndReturn(&callback_).Run(rv); 922 base::ResetAndReturn(&callback_).Run(rv);
950 } 923 }
951 924
952 return rv; 925 return rv;
953 } 926 }
954 927
955 int HttpCache::Transaction::DoGetBackend() { 928 int HttpCache::Transaction::DoGetBackend() {
956 cache_pending_ = true; 929 cache_pending_ = true;
957 next_state_ = STATE_GET_BACKEND_COMPLETE; 930 next_state_ = STATE_GET_BACKEND_COMPLETE;
958 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND); 931 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 mode_ = NONE; 1043 mode_ = NONE;
1071 next_state_ = STATE_SEND_REQUEST; 1044 next_state_ = STATE_SEND_REQUEST;
1072 return OK; 1045 return OK;
1073 } 1046 }
1074 1047
1075 if (mode_ == READ_WRITE) { 1048 if (mode_ == READ_WRITE) {
1076 mode_ = WRITE; 1049 mode_ = WRITE;
1077 next_state_ = STATE_CREATE_ENTRY; 1050 next_state_ = STATE_CREATE_ENTRY;
1078 return OK; 1051 return OK;
1079 } 1052 }
1053
1080 if (mode_ == UPDATE) { 1054 if (mode_ == UPDATE) {
1081 // There is no cache entry to update; proceed without caching. 1055 // There is no cache entry to update; proceed without caching.
1082 mode_ = NONE; 1056 mode_ = NONE;
1083 next_state_ = STATE_SEND_REQUEST; 1057 next_state_ = STATE_SEND_REQUEST;
1084 return OK; 1058 return OK;
1085 } 1059 }
1086 1060
1087 // The entry does not exist, and we are not permitted to create a new entry, 1061 // The entry does not exist, and we are not permitted to create a new entry,
1088 // so we must fail. 1062 // so we must fail.
1089 return ERR_CACHE_MISS; 1063 return ERR_CACHE_MISS;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 // TODO(jkarlin): If DoUpdateCachedResponse is also called for this 1261 // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
1288 // transaction then metadata will be written to cache twice. If prefetching 1262 // transaction then metadata will be written to cache twice. If prefetching
1289 // becomes more common, consider combining the writes. 1263 // becomes more common, consider combining the writes.
1290 1264
1291 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1265 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1292 tracked_objects::ScopedTracker tracking_profile( 1266 tracked_objects::ScopedTracker tracking_profile(
1293 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1267 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1294 "422516 HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch")); 1268 "422516 HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch"));
1295 1269
1296 next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE; 1270 next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE;
1297 return WriteResponseInfoToEntry(false); 1271 return WriteResponseInfoToEntry(false, io_callback_);
1298 } 1272 }
1299 1273
1300 int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete( 1274 int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
1301 int result) { 1275 int result) {
1302 // Restore the original value for this transaction. 1276 // Restore the original value for this transaction.
1303 response_.unused_since_prefetch = !response_.unused_since_prefetch; 1277 response_.unused_since_prefetch = !response_.unused_since_prefetch;
1304 next_state_ = STATE_CACHE_DISPATCH_VALIDATION; 1278 next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
1305 return OnWriteResponseInfoToEntryComplete(result); 1279 return OnWriteResponseInfoToEntryComplete(result);
1306 } 1280 }
1307 1281
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 int HttpCache::Transaction::DoStartPartialCacheValidation() { 1329 int HttpCache::Transaction::DoStartPartialCacheValidation() {
1356 if (mode_ == NONE) 1330 if (mode_ == NONE)
1357 return OK; 1331 return OK;
1358 1332
1359 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION; 1333 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
1360 return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_); 1334 return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
1361 } 1335 }
1362 1336
1363 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { 1337 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
1364 if (!result) { 1338 if (!result) {
1365 // This is the end of the request. 1339 ReleaseCacheEntry(EntryState::KEEP);
1366 if (mode_ & WRITE) { 1340 return 0;
1367 DoneWritingToEntry(true);
1368 } else {
1369 cache_->DoneReadingFromEntry(entry_, this);
1370 entry_ = NULL;
1371 }
1372 return result;
1373 } 1341 }
1374 1342
1375 if (result < 0) 1343 if (result < 0)
1376 return result; 1344 return result;
1377 1345
1378 partial_->PrepareCacheValidation(entry_->disk_entry, 1346 partial_->PrepareCacheValidation(entry_->disk_entry,
1379 &custom_request_->extra_headers); 1347 &custom_request_->extra_headers);
1380 1348
1381 if (reading_ && partial_->IsCurrentRangeCached()) { 1349 if (reading_ && partial_->IsCurrentRangeCached()) {
1382 next_state_ = STATE_CACHE_READ_DATA; 1350 next_state_ = STATE_CACHE_READ_DATA;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1402 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1435 if (IsCertificateError(result)) { 1403 if (IsCertificateError(result)) {
1436 // If we get a certificate error, then there is a certificate in ssl_info, 1404 // If we get a certificate error, then there is a certificate in ssl_info,
1437 // so GetResponseInfo() should never return NULL here. 1405 // so GetResponseInfo() should never return NULL here.
1438 DCHECK(response); 1406 DCHECK(response);
1439 response_.ssl_info = response->ssl_info; 1407 response_.ssl_info = response->ssl_info;
1440 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 1408 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
1441 DCHECK(response); 1409 DCHECK(response);
1442 response_.cert_request_info = response->cert_request_info; 1410 response_.cert_request_info = response->cert_request_info;
1443 } else if (response_.was_cached) { 1411 } else if (response_.was_cached) {
1444 DoneWritingToEntry(true); 1412 ReleaseCacheEntry(EntryState::KEEP);
1445 } 1413 }
1446 1414
1447 return result; 1415 return result;
1448 } 1416 }
1449 1417
1450 // We received the response headers and there is no error. 1418 // We received the response headers and there is no error.
1451 int HttpCache::Transaction::DoSuccessfulSendRequest() { 1419 int HttpCache::Transaction::DoSuccessfulSendRequest() {
1452 DCHECK(!new_response_); 1420 DCHECK(!new_response_);
1453 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); 1421 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
1454 1422
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 // the new response. 1458 // the new response.
1491 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); 1459 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST);
1492 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1460 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1493 response_ = HttpResponseInfo(); 1461 response_ = HttpResponseInfo();
1494 ResetNetworkTransaction(); 1462 ResetNetworkTransaction();
1495 new_response_ = NULL; 1463 new_response_ = NULL;
1496 next_state_ = STATE_SEND_REQUEST; 1464 next_state_ = STATE_SEND_REQUEST;
1497 return OK; 1465 return OK;
1498 } 1466 }
1499 1467
1468 if (handling_206_ && stopped_caching_ && partial_ &&
1469 partial_->IsLastRange() && !partial_->IsCurrentRangeCached() &&
1470 (mode_ & WRITE) && entry_) {
1471 // The current state of the transaction is:
1472 // * The client has requested that no addtional data be cached.
1473 // * The current network transaction spans the entire remainder of the
1474 // requested range.
1475 // * A cache entry exists and was being written to or updated.
1476 // * The current range is not cached.
1477 //
1478 // At this point it is safe to abandon the cache entry and proceed with just
1479 // the network transaction.
1480 next_state_ = STATE_NETWORK_READ;
1481 return AbandonCacheEntry(io_callback_);
1482 }
1483
1500 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { 1484 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
1501 // We have stored the full entry, but it changed and the server is 1485 // We have stored the full entry, but it changed and the server is
1502 // sending a range. We have to delete the old entry. 1486 // sending a range. We have to delete the old entry.
1503 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1487 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1504 DoneWritingToEntry(false); 1488 ReleaseCacheEntry(EntryState::DOOM);
1505 } 1489 }
1506 1490
1507 if (mode_ == WRITE && 1491 if (mode_ == WRITE &&
1508 transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) { 1492 transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
1509 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED); 1493 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
1510 } 1494 }
1511 1495
1512 // Invalidate any cached GET with a successful PUT or DELETE. 1496 // Invalidate any cached GET with a successful PUT or DELETE.
1513 if (mode_ == WRITE && 1497 if (mode_ == WRITE &&
1514 (request_->method == "PUT" || request_->method == "DELETE")) { 1498 (request_->method == "PUT" || request_->method == "DELETE")) {
1515 if (NonErrorResponse(new_response->headers->response_code())) { 1499 if (NonErrorResponse(new_response->headers->response_code())) {
1516 int ret = cache_->DoomEntry(cache_key_, NULL); 1500 int ret = cache_->DoomEntry(cache_key_, NULL);
1517 DCHECK_EQ(OK, ret); 1501 DCHECK_EQ(OK, ret);
1518 } 1502 }
1519 cache_->DoneWritingToEntry(entry_, true); 1503 ReleaseCacheEntry(EntryState::KEEP);
1520 entry_ = NULL;
1521 mode_ = NONE;
1522 } 1504 }
1523 1505
1524 // Invalidate any cached GET with a successful POST. 1506 // Invalidate any cached GET with a successful POST.
1525 if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && 1507 if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) &&
1526 request_->method == "POST" && 1508 request_->method == "POST" &&
1527 NonErrorResponse(new_response->headers->response_code())) { 1509 NonErrorResponse(new_response->headers->response_code())) {
1528 cache_->DoomMainEntryForUrl(request_->url); 1510 cache_->DoomMainEntryForUrl(request_->url);
1529 } 1511 }
1530 1512
1531 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1513 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 return rv; 1572 return rv;
1591 } 1573 }
1592 1574
1593 int HttpCache::Transaction::DoCacheWriteUpdatedResponse() { 1575 int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
1594 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1576 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1595 tracked_objects::ScopedTracker tracking_profile( 1577 tracked_objects::ScopedTracker tracking_profile(
1596 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1578 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1597 "422516 HttpCache::Transaction::DoCacheWriteUpdatedResponse")); 1579 "422516 HttpCache::Transaction::DoCacheWriteUpdatedResponse"));
1598 1580
1599 next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE; 1581 next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE;
1600 return WriteResponseInfoToEntry(false); 1582 return WriteResponseInfoToEntry(false, io_callback_);
1601 } 1583 }
1602 1584
1603 int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) { 1585 int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
1604 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1586 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
1605 return OnWriteResponseInfoToEntryComplete(result); 1587 return OnWriteResponseInfoToEntryComplete(result);
1606 } 1588 }
1607 1589
1608 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { 1590 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
1609 if (mode_ == UPDATE) { 1591 if (mode_ == UPDATE) {
1610 DCHECK(!handling_206_); 1592 DCHECK(!handling_206_);
1611 // We got a "not modified" response and already updated the corresponding 1593 // We got a "not modified" response and already updated the corresponding
1612 // cache entry above. 1594 // cache entry above.
1613 // 1595 //
1614 // By closing the cached entry now, we make sure that the 304 rather than 1596 // By closing the cached entry now, we make sure that the 304 rather than
1615 // the cached 200 response, is what will be returned to the user. 1597 // the cached 200 response, is what will be returned to the user.
1616 DoneWritingToEntry(true); 1598 ReleaseCacheEntry(EntryState::KEEP);
1617 } else if (entry_ && !handling_206_) { 1599 } else if (entry_ && !handling_206_) {
1618 DCHECK_EQ(READ_WRITE, mode_); 1600 DCHECK_EQ(READ_WRITE, mode_);
1619 if (!partial_ || partial_->IsLastRange()) { 1601 if (!partial_ || partial_->IsLastRange()) {
1620 cache_->ConvertWriterToReader(entry_); 1602 cache_->ConvertWriterToReader(entry_);
1621 mode_ = READ; 1603 mode_ = READ;
1622 } 1604 }
1623 // We no longer need the network transaction, so destroy it. 1605 // We no longer need the network transaction, so destroy it.
1624 final_upload_progress_ = network_trans_->GetUploadProgress(); 1606 final_upload_progress_ = network_trans_->GetUploadProgress();
1625 ResetNetworkTransaction(); 1607 ResetNetworkTransaction();
1626 } else if (entry_ && handling_206_ && truncated_ && 1608 } else if (entry_ && handling_206_ && truncated_ &&
(...skipping 18 matching lines...) Expand all
1645 } 1627 }
1646 1628
1647 // We change the value of Content-Length for partial content. 1629 // We change the value of Content-Length for partial content.
1648 if (handling_206_ && partial_) 1630 if (handling_206_ && partial_)
1649 partial_->FixContentLength(new_response_->headers.get()); 1631 partial_->FixContentLength(new_response_->headers.get());
1650 1632
1651 response_ = *new_response_; 1633 response_ = *new_response_;
1652 1634
1653 if (request_->method == "HEAD") { 1635 if (request_->method == "HEAD") {
1654 // This response is replacing the cached one. 1636 // This response is replacing the cached one.
1655 DoneWritingToEntry(false); 1637 ReleaseCacheEntry(EntryState::DOOM);
1656 mode_ = NONE; 1638 new_response_ = nullptr;
1657 new_response_ = NULL;
1658 return OK; 1639 return OK;
1659 } 1640 }
1660 1641
1661 if (handling_206_ && !CanResume(false)) { 1642 if (handling_206_ && !CanResume(false)) {
1662 // There is no point in storing this resource because it will never be used. 1643 // There is no point in storing this resource because it will never be used.
1663 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries. 1644 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
1664 DoneWritingToEntry(false); 1645 ReleaseCacheEntry(EntryState::DOOM);
1665 if (partial_) 1646 if (partial_)
1666 partial_->FixResponseHeaders(response_.headers.get(), true); 1647 partial_->FixResponseHeaders(response_.headers.get(), true);
1667 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1648 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1668 return OK; 1649 return OK;
1669 } 1650 }
1670 1651
1671 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1652 next_state_ = STATE_CACHE_WRITE_RESPONSE;
1672 return OK; 1653 return OK;
1673 } 1654 }
1674 1655
1675 int HttpCache::Transaction::DoCacheWriteResponse() { 1656 int HttpCache::Transaction::DoCacheWriteResponse() {
1676 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1657 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1677 tracked_objects::ScopedTracker tracking_profile( 1658 tracked_objects::ScopedTracker tracking_profile(
1678 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1659 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1679 "422516 HttpCache::Transaction::DoCacheWriteResponse")); 1660 "422516 HttpCache::Transaction::DoCacheWriteResponse"));
1680 1661
1681 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1662 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1682 return WriteResponseInfoToEntry(truncated_); 1663 return WriteResponseInfoToEntry(truncated_, io_callback_);
1683 } 1664 }
1684 1665
1685 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1666 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1686 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1667 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1687 return OnWriteResponseInfoToEntryComplete(result); 1668 return OnWriteResponseInfoToEntryComplete(result);
1688 } 1669 }
1689 1670
1690 int HttpCache::Transaction::DoTruncateCachedData() { 1671 int HttpCache::Transaction::DoTruncateCachedData() {
1691 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1672 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1692 if (!entry_) 1673 if (!entry_)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1768 io_callback_); 1749 io_callback_);
1769 } 1750 }
1770 1751
1771 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1752 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
1772 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1753 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1773 if (result != response_.metadata->size()) 1754 if (result != response_.metadata->size())
1774 return OnCacheReadError(result, false); 1755 return OnCacheReadError(result, false);
1775 return OK; 1756 return OK;
1776 } 1757 }
1777 1758
1759 int HttpCache::Transaction::DoSwitchToNetwork() {
1760 DCHECK(entry_);
1761 DCHECK(mode_ & WRITE);
1762
1763 // If the transaction is currently reading from the cache, then it should have
1764 // a valid partial state. I.e. only part of the requested resource could be
1765 // fulfiled via the cache. If the entire request was being fulfiled via the
1766 // cache, the transaction shouldn't be trying to switch to the network at this
1767 // point, and mode_ should be READ.
1768 DCHECK_IMPLIES(!network_trans_, partial_);
1769
1770 // The network transaction can be trivially reused if it can promise to
1771 // deliver all the bits necessary to fulfil the original request. If so,
1772 // abandon the cache entry and continue with a network read.
1773 if (network_trans_ && (!partial_ || partial_->IsLastRange())) {
1774 next_state_ = STATE_NETWORK_READ;
1775 return AbandonCacheEntry(io_callback_);
1776 }
1777
1778 if (request_->method != "GET") {
1779 // We have a non-GET request that the cache or network can partially fulfil.
1780 // In other words, at some point the transaction is going to have to issue a
1781 // partial network request to fulfil this non-GET request. Let's just ignore
1782 // the StopCaching() directive for now.
1783 stopped_caching_ = false;
1784 next_state_ = network_trans_ ? STATE_NETWORK_READ : STATE_CACHE_READ_DATA;
1785 return OK;
1786 }
1787
1788 // The existing network transaction doesn't cover the entire range we wanted.
1789 // Let's discard the network transaction and create a new one that will cover
1790 // the entire range we need.
1791 if (network_trans_)
1792 ResetNetworkTransaction();
1793
1794 if (!partial_->SkipCacheForRemainder()) {
1795 // PartialData only refuses to switch to network reads if the entire
1796 // resource has been accounted for. There's nothing more to do.
1797 return OK;
1798 }
1799
1800 // The new network request that's going to be issued has to be validated
1801 // against the existing cache entry. By extension, this also validates the new
1802 // request against the portion that has already been sent to our client.
1803 partial_->PrepareCacheValidation(entry_->disk_entry,
1804 &custom_request_->extra_headers);
1805
1806 // Since we called SkipCacheForRemainder(), the partial_ state should now
1807 // assume that the remainder of the resource is not cached.
1808 DCHECK(!partial_->IsCurrentRangeCached());
1809 DCHECK(partial_->IsLastRange());
1810
1811 // READ shouldn't reach here at all. WRITE/UPDATE require a network_trans_
1812 // that spans the entire request range and is handled at the top of this
1813 // function. At this point we should be left with just READ_WRITE.
1814 DCHECK_EQ(mode_, READ_WRITE);
1815
1816 // Start validating the cache. DoSuccessfulSendRequest() will now bear the
1817 // responsibility of abandoning the cache entry if the new network transaction
1818 // is successfully validated.
1819 return BeginCacheValidation();
1820 }
1821
1778 int HttpCache::Transaction::DoNetworkRead() { 1822 int HttpCache::Transaction::DoNetworkRead() {
1823 DCHECK_GT(read_buf_len_, 0);
1824
1825 io_buf_len_ = read_buf_len_;
1779 next_state_ = STATE_NETWORK_READ_COMPLETE; 1826 next_state_ = STATE_NETWORK_READ_COMPLETE;
1780 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1827 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
1781 } 1828 }
1782 1829
1783 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1830 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1784 DCHECK(mode_ & WRITE || mode_ == NONE); 1831 DCHECK(mode_ & WRITE || mode_ == NONE);
1785 1832
1786 if (!cache_.get()) 1833 if (!cache_.get())
1787 return ERR_UNEXPECTED; 1834 return ERR_UNEXPECTED;
1788 1835
1789 // If there is an error or we aren't saving the data, we are done; just wait 1836 // If there is an error or we aren't saving the data, we are done; just wait
1790 // until the destructor runs to see if we can keep the data. 1837 // until the destructor runs to see if we can keep the data.
1791 if (mode_ == NONE || result < 0) 1838 if (mode_ == NONE || result < 0)
1792 return result; 1839 return result;
1793 1840
1794 next_state_ = STATE_CACHE_WRITE_DATA; 1841 next_state_ = STATE_CACHE_WRITE_DATA;
1795 return result; 1842 return result;
1796 } 1843 }
1797 1844
1798 int HttpCache::Transaction::DoCacheReadData() { 1845 int HttpCache::Transaction::DoCacheReadData() {
1846 DCHECK_GT(read_buf_len_, 0);
1847
1799 if (request_->method == "HEAD") 1848 if (request_->method == "HEAD")
1800 return 0; 1849 return 0;
1801 1850
1802 DCHECK(entry_); 1851 DCHECK(entry_);
1803 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 1852 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1853 io_buf_len_ = read_buf_len_;
1804 1854
1805 if (net_log_.IsCapturing()) 1855 if (net_log_.IsCapturing())
1806 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA); 1856 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
1807 if (partial_) { 1857 if (partial_) {
1808 return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_, 1858 return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_,
1809 io_callback_); 1859 io_callback_);
1810 } 1860 }
1811 1861
1812 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, 1862 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_,
1813 read_buf_.get(), io_buf_len_, 1863 read_buf_.get(), io_buf_len_,
1814 io_callback_); 1864 io_callback_);
1815 } 1865 }
1816 1866
1817 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1867 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
1818 if (net_log_.IsCapturing()) { 1868 if (net_log_.IsCapturing()) {
1819 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1869 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
1820 result); 1870 result);
1821 } 1871 }
1822 1872
1823 if (!cache_.get()) 1873 if (!cache_.get())
1824 return ERR_UNEXPECTED; 1874 return ERR_UNEXPECTED;
1825 1875
1826 if (partial_) { 1876 if (partial_) {
1827 // Partial requests are confusing to report in histograms because they may 1877 // Partial requests are confusing to report in histograms because they may
1828 // have multiple underlying requests. 1878 // have multiple underlying requests.
1829 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1879 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1830 return DoPartialCacheReadCompleted(result); 1880 return DoPartialCacheReadCompleted(result);
1831 } 1881 }
1832 1882
1833 if (result > 0) { 1883 if (result < 0)
1834 read_offset_ += result;
1835 } else if (result == 0) { // End of file.
1836 RecordHistograms();
1837 cache_->DoneReadingFromEntry(entry_, this);
1838 entry_ = NULL;
1839 } else {
1840 return OnCacheReadError(result, false); 1884 return OnCacheReadError(result, false);
1841 } 1885
1886 if (result == 0)
1887 ReleaseCacheEntry(EntryState::KEEP);
1888
1889 read_offset_ += result;
1842 return result; 1890 return result;
1843 } 1891 }
1844 1892
1845 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1893 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
1846 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1894 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
1847 write_len_ = num_bytes; 1895 write_len_ = num_bytes;
1848 if (entry_) { 1896 if (entry_) {
1849 if (net_log_.IsCapturing()) 1897 if (net_log_.IsCapturing())
1850 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); 1898 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
1851 } 1899 }
1852 1900
1853 if (!entry_ || !num_bytes) 1901 if (!entry_ || !num_bytes)
1854 return num_bytes; 1902 return num_bytes;
1855 1903
1856 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1904 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1857 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(), 1905 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(),
1858 num_bytes, io_callback_); 1906 num_bytes, io_callback_);
1859 } 1907 }
1860 1908
1861 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 1909 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
1862 if (entry_) { 1910 if (entry_ && net_log_.IsCapturing()) {
1863 if (net_log_.IsCapturing()) { 1911 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
1864 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1912 result);
1865 result);
1866 }
1867 } 1913 }
1914
1868 if (!cache_.get()) 1915 if (!cache_.get())
1869 return ERR_UNEXPECTED; 1916 return ERR_UNEXPECTED;
1870 1917
1871 if (result != write_len_) { 1918 if (result != write_len_) {
1872 DLOG(ERROR) << "failed to write response data to cache"; 1919 DLOG(ERROR) << "failed to write response data to cache";
1873 DoneWritingToEntry(false); 1920 ReleaseCacheEntry(EntryState::DOOM);
1874 1921
1875 // We want to ignore errors writing to disk and just keep reading from 1922 // We want to ignore errors writing to disk and just keep reading from
1876 // the network. 1923 // the network.
1877 result = write_len_; 1924 result = write_len_;
1925
1926 // TODO(asanka): More needs to be done to ignore the error and keep reading
1927 // from the network. E.g. if the cache entry was sparse, it is possible that
1928 // the current network_trans_ can't fulfil the entire requested range.
1929 // Consider setting up state to perform an immediate STATE_SWITCH_TO_NETWORK
1930 // at the next Read() instead of releasing the entry now.
1878 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) { 1931 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
1879 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1932 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1880 int64 body_size = response_.headers->GetContentLength(); 1933 int64 body_size = response_.headers->GetContentLength();
1881 if (body_size >= 0 && body_size <= current_size) 1934 if (body_size >= 0 && body_size <= current_size)
1882 done_reading_ = true; 1935 done_reading_ = true;
1883 } 1936 }
1884 1937
1885 if (partial_) { 1938 if (partial_) {
1886 // This may be the last request. 1939 // The transaction needs to update partial state under the following
1887 if (result != 0 || truncated_ || 1940 // circumstances:
1888 !(partial_->IsLastRange() || mode_ == WRITE)) { 1941 const bool need_to_update_partial_state =
1942 // Still reading. The partial state needs to be updated to account for
1943 // the data read so far.
1944 result != 0 ||
1945
1946 // Reached the end of one network request, but more transactions may be
1947 // necessary to fulfil the request. DoPartialNetworkReadCompleted()
1948 // initiates additional network transactions as needed.
1949 truncated_ ||
1950
1951 // If this isn't the last range, then more network transactions may be
1952 // necessary. But skip this step for new cache entries (mode_ == WRITE).
1953 // Range requests with new cache entries will have
1954 // partial_->IsLastRange() set to false. IsLastRange() is only set to
1955 // true when validating the last range of an existing cache entry.
1956 (!partial_->IsLastRange() && mode_ != WRITE);
1957
1958 if (need_to_update_partial_state)
1889 return DoPartialNetworkReadCompleted(result); 1959 return DoPartialNetworkReadCompleted(result);
1890 }
1891 } 1960 }
1892 1961
1893 if (result == 0) { 1962 if (result == 0) {
1894 // End of file. This may be the result of a connection problem so see if we 1963 // If the entire response body was successfully read, then the transaction
1895 // have to keep the entry around to be flagged as truncated later on. 1964 // should release the cache entry.
1896 if (done_reading_ || !entry_ || partial_ || 1965 //
1897 response_.headers->GetContentLength() <= 0) { 1966 // While response == 0 typically indicates EOF, it is possible for that to
1898 DoneWritingToEntry(true); 1967 // happen due to a connection problem. In the latter case the resulting
rvargas (doing something else) 2015/09/21 22:06:00 tiny nit: maybe remove "the resulting" and "call"
1968 // AbandonCacheEntry() call marks the cache entry as truncated.
1969 //
1970 // A succesful receipt of the response body is considered to be indicated by
1971 // one of:
1972 // * done_reading_ : Received response body was of expected size.
1973 // * Content-Length <= 0 : Response body size was not known.
1974 // * partial_ :
1975 if (entry_ && (done_reading_ || partial_ ||
1976 response_.headers->GetContentLength() <= 0)) {
1977 ReleaseCacheEntry(EntryState::KEEP);
1978 } else {
1979 AbandonCacheEntry(CompletionCallback());
1899 } 1980 }
1900 } 1981 }
1901 1982
1902 return result; 1983 return result;
1903 } 1984 }
1904 1985
1905 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1906 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1907 return WriteResponseInfoToEntry(true);
1908 }
1909
1910 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
1911 return OnWriteResponseInfoToEntryComplete(result);
1912 }
1913
1914 //----------------------------------------------------------------------------- 1986 //-----------------------------------------------------------------------------
1915 1987
1916 void HttpCache::Transaction::ReadCertChain() { 1988 void HttpCache::Transaction::ReadCertChain() {
1917 std::string key = 1989 std::string key =
1918 GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle()); 1990 GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle());
1919 const X509Certificate::OSCertHandles& intermediates = 1991 const X509Certificate::OSCertHandles& intermediates =
1920 response_.ssl_info.cert->GetIntermediateCertificates(); 1992 response_.ssl_info.cert->GetIntermediateCertificates();
1921 int dist_from_root = intermediates.size(); 1993 int dist_from_root = intermediates.size();
1922 1994
1923 scoped_refptr<SharedChainData> shared_chain_data( 1995 scoped_refptr<SharedChainData> shared_chain_data(
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2161 UpdateTransactionPattern(PATTERN_ENTRY_USED); 2233 UpdateTransactionPattern(PATTERN_ENTRY_USED);
2162 return SetupEntryForRead(); 2234 return SetupEntryForRead();
2163 } else { 2235 } else {
2164 // Make the network request conditional, to see if we may reuse our cached 2236 // Make the network request conditional, to see if we may reuse our cached
2165 // response. If we cannot do so, then we just resort to a normal fetch. 2237 // response. If we cannot do so, then we just resort to a normal fetch.
2166 // Our mode remains READ_WRITE for a conditional request. Even if the 2238 // Our mode remains READ_WRITE for a conditional request. Even if the
2167 // conditionalization fails, we don't switch to WRITE mode until we 2239 // conditionalization fails, we don't switch to WRITE mode until we
2168 // know we won't be falling back to using the cache entry in the 2240 // know we won't be falling back to using the cache entry in the
2169 // LOAD_FROM_CACHE_IF_OFFLINE case. 2241 // LOAD_FROM_CACHE_IF_OFFLINE case.
2170 if (!ConditionalizeRequest()) { 2242 if (!ConditionalizeRequest()) {
2243 // Conditionalization should only depend on the state of the cache prior
2244 // to starting the request and the request method. Failure is unexpected
2245 // after the client has started reading the stream.
2246 DCHECK(!reading_);
2247
2171 couldnt_conditionalize_request_ = true; 2248 couldnt_conditionalize_request_ = true;
2172 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); 2249 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
2173 if (partial_) 2250 if (partial_)
2174 return DoRestartPartialRequest(); 2251 return DoRestartPartialRequest();
2175 2252
2176 DCHECK_NE(206, response_.headers->response_code()); 2253 DCHECK_NE(206, response_.headers->response_code());
2177 } 2254 }
2178 next_state_ = STATE_SEND_REQUEST; 2255 next_state_ = STATE_SEND_REQUEST;
2179 } 2256 }
2180 return OK; 2257 return OK;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 response_.headers->EnumerateHeader( 2316 response_.headers->EnumerateHeader(
2240 NULL, 2317 NULL,
2241 kValidationHeaders[i].related_response_header_name, 2318 kValidationHeaders[i].related_response_header_name,
2242 &validator); 2319 &validator);
2243 2320
2244 if (response_.headers->response_code() != 200 || truncated_ || 2321 if (response_.headers->response_code() != 200 || truncated_ ||
2245 validator.empty() || validator != external_validation_.values[i]) { 2322 validator.empty() || validator != external_validation_.values[i]) {
2246 // The externally conditionalized request is not a validation request 2323 // The externally conditionalized request is not a validation request
2247 // for our existing cache entry. Proceed with caching disabled. 2324 // for our existing cache entry. Proceed with caching disabled.
2248 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2325 UpdateTransactionPattern(PATTERN_NOT_COVERED);
2249 DoneWritingToEntry(true); 2326 ReleaseCacheEntry(EntryState::KEEP);
2250 } 2327 }
2251 } 2328 }
2252 2329
2253 // TODO(ricea): This calculation is expensive to perform just to collect 2330 // TODO(ricea): This calculation is expensive to perform just to collect
2254 // statistics. Either remove it or use the result, depending on the result of 2331 // statistics. Either remove it or use the result, depending on the result of
2255 // the experiment. 2332 // the experiment.
2256 ExternallyConditionalizedType type = 2333 ExternallyConditionalizedType type =
2257 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE; 2334 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE;
2258 if (mode_ == NONE) 2335 if (mode_ == NONE)
2259 type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS; 2336 type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS;
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
2567 IgnoreRangeRequest(); 2644 IgnoreRangeRequest();
2568 return true; 2645 return true;
2569 } 2646 }
2570 2647
2571 void HttpCache::Transaction::IgnoreRangeRequest() { 2648 void HttpCache::Transaction::IgnoreRangeRequest() {
2572 // We have a problem. We may or may not be reading already (in which case we 2649 // We have a problem. We may or may not be reading already (in which case we
2573 // returned the headers), but we'll just pretend that this request is not 2650 // returned the headers), but we'll just pretend that this request is not
2574 // using the cache and see what happens. Most likely this is the first 2651 // using the cache and see what happens. Most likely this is the first
2575 // response from the server (it's not changing its mind midway, right?). 2652 // response from the server (it's not changing its mind midway, right?).
2576 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2653 UpdateTransactionPattern(PATTERN_NOT_COVERED);
2577 if (mode_ & WRITE) 2654 ReleaseCacheEntry(mode_ == WRITE ? EntryState::DOOM : EntryState::KEEP);
2578 DoneWritingToEntry(mode_ != WRITE); 2655 partial_.reset();
2579 else if (mode_ & READ && entry_)
2580 cache_->DoneReadingFromEntry(entry_, this);
2581
2582 partial_.reset(NULL);
2583 entry_ = NULL;
2584 mode_ = NONE;
2585 } 2656 }
2586 2657
2587 void HttpCache::Transaction::FixHeadersForHead() { 2658 void HttpCache::Transaction::FixHeadersForHead() {
2588 if (response_.headers->response_code() == 206) { 2659 if (response_.headers->response_code() == 206) {
2589 response_.headers->RemoveHeader("Content-Range"); 2660 response_.headers->RemoveHeader("Content-Range");
2590 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK"); 2661 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK");
2591 } 2662 }
2592 } 2663 }
2593 2664
2594 int HttpCache::Transaction::SetupEntryForRead() { 2665 int HttpCache::Transaction::SetupEntryForRead() {
(...skipping 29 matching lines...) Expand all
2624 int rv = 0; 2695 int rv = 0;
2625 if (!partial_ || !data_len) { 2696 if (!partial_ || !data_len) {
2626 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, 2697 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback,
2627 true); 2698 true);
2628 } else { 2699 } else {
2629 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); 2700 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
2630 } 2701 }
2631 return rv; 2702 return rv;
2632 } 2703 }
2633 2704
2634 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { 2705 int HttpCache::Transaction::WriteResponseInfoToEntry(
2706 bool truncated,
2707 const CompletionCallback& callback) {
2635 if (!entry_) 2708 if (!entry_)
2636 return OK; 2709 return OK;
2637 2710
2638 if (net_log_.IsCapturing()) 2711 if (net_log_.IsCapturing())
2639 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2712 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
2640 2713
2641 // Do not cache no-store content. Do not cache content with cert errors 2714 // Do not cache no-store content. Do not cache content with cert errors
2642 // either. This is to prevent not reporting net errors when loading a 2715 // either. This is to prevent not reporting net errors when loading a
2643 // resource from the cache. When we load a page over HTTPS with a cert error 2716 // resource from the cache. When we load a page over HTTPS with a cert error
2644 // we show an SSL blocking page. If the user clicks proceed we reload the 2717 // we show an SSL blocking page. If the user clicks proceed we reload the
2645 // resource ignoring the errors. The loaded resource is then cached. If that 2718 // resource ignoring the errors. The loaded resource is then cached. If that
2646 // resource is subsequently loaded from the cache, no net error is reported 2719 // resource is subsequently loaded from the cache, no net error is reported
2647 // (even though the cert status contains the actual errors) and no SSL 2720 // (even though the cert status contains the actual errors) and no SSL
2648 // blocking page is shown. An alternative would be to reverse-map the cert 2721 // blocking page is shown. An alternative would be to reverse-map the cert
2649 // status to a net error and replay the net error. 2722 // status to a net error and replay the net error.
2650 if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || 2723 if ((response_.headers->HasHeaderValue("cache-control", "no-store")) ||
2651 IsCertStatusError(response_.ssl_info.cert_status)) { 2724 IsCertStatusError(response_.ssl_info.cert_status)) {
2652 DoneWritingToEntry(false); 2725 ReleaseCacheEntry(EntryState::DOOM);
2653 if (net_log_.IsCapturing()) 2726 if (net_log_.IsCapturing())
2654 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2727 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
2655 return OK; 2728 return OK;
2656 } 2729 }
2657 2730
2658 // cert_cache() will be null if the CertCacheTrial field trial is disabled. 2731 // cert_cache() will be null if the CertCacheTrial field trial is disabled.
2659 if (cache_->cert_cache() && response_.ssl_info.is_valid()) 2732 if (cache_->cert_cache() && response_.ssl_info.is_valid())
2660 WriteCertChain(); 2733 WriteCertChain();
2661 2734
2662 if (truncated) 2735 if (truncated)
2663 DCHECK_EQ(200, response_.headers->response_code()); 2736 DCHECK_EQ(200, response_.headers->response_code());
2664 2737
2665 // When writing headers, we normally only write the non-transient headers. 2738 // When writing headers, we normally only write the non-transient headers.
2666 bool skip_transient_headers = true; 2739 bool skip_transient_headers = true;
2667 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2740 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2668 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2741 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2669 data->Done(); 2742 data->Done();
2670 2743
2671 io_buf_len_ = data->pickle()->size(); 2744 io_buf_len_ = data->pickle()->size();
2672 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), 2745 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
2673 io_buf_len_, io_callback_, true); 2746 io_buf_len_, callback, true);
2674 } 2747 }
2675 2748
2676 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2749 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2677 if (!entry_) 2750 if (!entry_)
2678 return OK; 2751 return OK;
2679 if (net_log_.IsCapturing()) { 2752 if (net_log_.IsCapturing()) {
2680 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 2753 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
2681 result); 2754 result);
2682 } 2755 }
2683 2756
2684 if (result != io_buf_len_) { 2757 if (result != io_buf_len_) {
2685 DLOG(ERROR) << "failed to write response info to cache"; 2758 DLOG(ERROR) << "failed to write response info to cache";
2686 DoneWritingToEntry(false); 2759 ReleaseCacheEntry(EntryState::DOOM);
2687 } 2760 }
2688 return OK; 2761 return OK;
2689 } 2762 }
2690 2763
2691 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2764 void HttpCache::Transaction::ReleaseCacheEntry(EntryState entry_state) {
2692 if (!entry_) 2765 if (!cache_ || !entry_)
2693 return; 2766 return;
2694 2767
2695 RecordHistograms(); 2768 cache_->DoneWithEntry(entry_, this, entry_state);
2696 2769 entry_ = nullptr;
2697 cache_->DoneWritingToEntry(entry_, success); 2770 mode_ = NONE;
2698 entry_ = NULL;
2699 mode_ = NONE; // switch to 'pass through' mode
2700 } 2771 }
2701 2772
2702 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2773 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2703 DLOG(ERROR) << "ReadData failed: " << result; 2774 DLOG(ERROR) << "ReadData failed: " << result;
2704 const int result_for_histogram = std::max(0, -result); 2775 const int result_for_histogram = std::max(0, -result);
2705 if (restart) { 2776 if (restart) {
2706 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2777 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2707 result_for_histogram); 2778 result_for_histogram);
2708 } else { 2779 } else {
2709 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 2780 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2710 result_for_histogram); 2781 result_for_histogram);
2711 } 2782 }
2712 2783
2713 // Avoid using this entry in the future. 2784 // Avoid using this entry in the future.
2714 if (cache_.get()) 2785 if (cache_.get())
2715 cache_->DoomActiveEntry(cache_key_); 2786 cache_->DoomActiveEntry(cache_key_);
2716 2787
2717 if (restart) { 2788 if (restart) {
2718 DCHECK(!reading_); 2789 DCHECK(!reading_);
2719 DCHECK(!network_trans_.get()); 2790 DCHECK(!network_trans_.get());
2720 cache_->DoneWithEntry(entry_, this, false); 2791 ReleaseCacheEntry(EntryState::DOOM);
2721 entry_ = NULL;
2722 is_sparse_ = false; 2792 is_sparse_ = false;
2723 partial_.reset(); 2793 partial_.reset();
2724 next_state_ = STATE_GET_BACKEND; 2794 next_state_ = STATE_GET_BACKEND;
2725 return OK; 2795 return OK;
2726 } 2796 }
2727 2797
2728 return ERR_CACHE_READ_FAILURE; 2798 return ERR_CACHE_READ_FAILURE;
2729 } 2799 }
2730 2800
2731 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 2801 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2732 if (entry_lock_waiting_since_ != start_time) 2802 if (entry_lock_waiting_since_ != start_time)
2733 return; 2803 return;
2734 2804
2735 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 2805 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2736 2806
2737 if (!cache_) 2807 if (!cache_)
2738 return; 2808 return;
2739 2809
2740 cache_->RemovePendingTransaction(this); 2810 cache_->RemovePendingTransaction(this);
2741 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 2811 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2742 } 2812 }
2743 2813
2744 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 2814 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
2745 DVLOG(2) << "DoomPartialEntry"; 2815 DVLOG(2) << "DoomPartialEntry";
2746 int rv = cache_->DoomEntry(cache_key_, NULL); 2816 ReleaseCacheEntry(EntryState::DOOM);
2747 DCHECK_EQ(OK, rv);
2748 cache_->DoneWithEntry(entry_, this, false);
2749 entry_ = NULL;
2750 is_sparse_ = false; 2817 is_sparse_ = false;
2751 truncated_ = false; 2818 truncated_ = false;
2752 if (delete_object) 2819 if (delete_object)
2753 partial_.reset(NULL); 2820 partial_.reset();
2754 } 2821 }
2755 2822
2756 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { 2823 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
2757 partial_->OnNetworkReadCompleted(result); 2824 partial_->OnNetworkReadCompleted(result);
2758 2825
2759 if (result == 0) { 2826 if (result == 0) {
2760 // We need to move on to the next range. 2827 // We need to move on to the next range.
2761 ResetNetworkTransaction(); 2828 ResetNetworkTransaction();
2762 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 2829 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
2763 } 2830 }
(...skipping 11 matching lines...) Expand all
2775 } 2842 }
2776 return result; 2843 return result;
2777 } 2844 }
2778 2845
2779 int HttpCache::Transaction::DoRestartPartialRequest() { 2846 int HttpCache::Transaction::DoRestartPartialRequest() {
2780 // The stored data cannot be used. Get rid of it and restart this request. 2847 // The stored data cannot be used. Get rid of it and restart this request.
2781 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST); 2848 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST);
2782 2849
2783 // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt 2850 // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt
2784 // to Doom the entry again). 2851 // to Doom the entry again).
2852 ResetPartialState(!range_requested_);
2785 mode_ = WRITE; 2853 mode_ = WRITE;
2786 ResetPartialState(!range_requested_);
2787 next_state_ = STATE_CREATE_ENTRY; 2854 next_state_ = STATE_CREATE_ENTRY;
2788 return OK; 2855 return OK;
2789 } 2856 }
2790 2857
2791 void HttpCache::Transaction::ResetPartialState(bool delete_object) { 2858 void HttpCache::Transaction::ResetPartialState(bool delete_object) {
2792 partial_->RestoreHeaders(&custom_request_->extra_headers); 2859 partial_->RestoreHeaders(&custom_request_->extra_headers);
2793 DoomPartialEntry(delete_object); 2860 DoomPartialEntry(delete_object);
2794 2861
2795 if (!delete_object) { 2862 if (!delete_object) {
2796 // The simplest way to re-initialize partial_ is to create a new object. 2863 // The simplest way to re-initialize partial_ is to create a new object.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2852 void HttpCache::Transaction::UpdateTransactionPattern( 2919 void HttpCache::Transaction::UpdateTransactionPattern(
2853 TransactionPattern new_transaction_pattern) { 2920 TransactionPattern new_transaction_pattern) {
2854 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2921 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2855 return; 2922 return;
2856 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED || 2923 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED ||
2857 new_transaction_pattern == PATTERN_NOT_COVERED); 2924 new_transaction_pattern == PATTERN_NOT_COVERED);
2858 transaction_pattern_ = new_transaction_pattern; 2925 transaction_pattern_ = new_transaction_pattern;
2859 } 2926 }
2860 2927
2861 void HttpCache::Transaction::RecordHistograms() { 2928 void HttpCache::Transaction::RecordHistograms() {
2862 DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_); 2929 if (transaction_pattern_ == PATTERN_UNDEFINED || !cache_.get() ||
2863 if (!cache_.get() || !cache_->GetCurrentBackend() || 2930 !cache_->GetCurrentBackend() ||
2864 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE || 2931 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
2865 cache_->mode() != NORMAL || request_->method != "GET") { 2932 cache_->mode() != NORMAL || request_->method != "GET") {
2866 return; 2933 return;
2867 } 2934 }
2868 UMA_HISTOGRAM_ENUMERATION( 2935 UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern", transaction_pattern_,
2869 "HttpCache.Pattern", transaction_pattern_, PATTERN_MAX); 2936 PATTERN_MAX);
2870 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2937 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2871 return; 2938 return;
2872 DCHECK(!range_requested_); 2939 DCHECK(!range_requested_);
2873 DCHECK(!first_cache_access_since_.is_null()); 2940 DCHECK(!first_cache_access_since_.is_null());
2874 2941
2875 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 2942 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2876 2943
2877 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 2944 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2878 2945
2879 bool did_send_request = !send_request_since_.is_null(); 2946 bool did_send_request = !send_request_since_.is_null();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2933 } 3000 }
2934 default: 3001 default:
2935 NOTREACHED(); 3002 NOTREACHED();
2936 } 3003 }
2937 } 3004 }
2938 3005
2939 void HttpCache::Transaction::OnIOComplete(int result) { 3006 void HttpCache::Transaction::OnIOComplete(int result) {
2940 DoLoop(result); 3007 DoLoop(result);
2941 } 3008 }
2942 3009
3010 int HttpCache::Transaction::AbandonCacheEntry(
3011 const CompletionCallback& callback) {
3012 DCHECK(abandon_cache_entry_callback_.is_null());
3013 // Is the cache entry is sparse or if the entry is complete? Then the entry
rvargas (doing something else) 2015/09/21 22:06:00 needs some rewording :). I guess you were going fo
3014 // doesn't need to be marked as truncated.
3015 //
3016 // * done_reading_: All pertinent response data has been written.
3017 // * !(mode_ & WRITE): This transaction wasn't writing to the entry. Leave
3018 // it be.
3019 // * is_sparse_: Pre-existing sparse entry.
3020 // * (partial_ && !truncated_): New sparse entry.
3021 if (done_reading_ || !(mode_ & WRITE) || is_sparse_ ||
3022 (partial_ && !truncated_)) {
3023 ReleaseCacheEntry(EntryState::KEEP);
3024 return OK;
3025 }
3026
3027 // If the caller hasn't started reading (implies that no response data was
3028 // written) or if the request can't be resumed, then another transaction is
3029 // unlikely to be able to use a partial cache entry for this request.
3030 if (!reading_ || !CanResume(true)) {
3031 ReleaseCacheEntry(EntryState::DOOM);
3032 return OK;
3033 }
3034
3035 // If we get here, the cache entry only contains part of the response and can
3036 // be resumed in the future. Mark it as truncated so it'll be handled
3037 // correctly.
3038 // TODO(asanka): Let's get rid of a persistent truncated flag and make it
3039 // implicit based on what we find in the cache the next time the entry is
3040 // opened.
3041 truncated_ = true;
3042 int result = WriteResponseInfoToEntry(
3043 true, base::Bind(&HttpCache::Transaction::OnAbandonCacheEntryIOComplete,
3044 weak_factory_.GetWeakPtr()));
3045 if (result < 0 && result != ERR_IO_PENDING)
3046 return result;
3047
3048 if (callback.is_null()) {
3049 ReleaseCacheEntry(EntryState::KEEP);
3050 return OK;
3051 }
3052
3053 abandon_cache_entry_callback_ = callback;
3054 return result;
3055 }
3056
3057 void HttpCache::Transaction::OnAbandonCacheEntryIOComplete(int result) {
3058 result = OnWriteResponseInfoToEntryComplete(result);
3059 ReleaseCacheEntry(EntryState::KEEP);
3060 if (!abandon_cache_entry_callback_.is_null())
3061 base::ResetAndReturn(&abandon_cache_entry_callback_).Run(result);
3062 }
3063
2943 } // namespace net 3064 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698