Chromium Code Reviews| 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_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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |