Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 | 8 |
| 9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 | 87 |
| 88 HttpUtil::ValuesIterator v(h.values_begin(), h.values_end(), ','); | 88 HttpUtil::ValuesIterator v(h.values_begin(), h.values_end(), ','); |
| 89 while (v.GetNext()) { | 89 while (v.GetNext()) { |
| 90 if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value)) | 90 if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value)) |
| 91 return true; | 91 return true; |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 return false; | 94 return false; |
| 95 } | 95 } |
| 96 | 96 |
| 97 // Indicates DoCacheWriteResponse to mark the entry as incomplete. | |
| 98 static const int kTruncatedEntry = 1; | |
|
eroman
2009/12/17 05:21:42
This can be deleted now yes?
rvargas (doing something else)
2009/12/17 18:30:12
Removed. Thanks!.
| |
| 99 | |
| 97 //----------------------------------------------------------------------------- | 100 //----------------------------------------------------------------------------- |
| 98 | 101 |
| 99 HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support) | 102 HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support) |
| 100 : next_state_(STATE_NONE), | 103 : next_state_(STATE_NONE), |
| 101 request_(NULL), | 104 request_(NULL), |
| 102 cache_(cache->AsWeakPtr()), | 105 cache_(cache->AsWeakPtr()), |
| 103 entry_(NULL), | 106 entry_(NULL), |
| 104 new_entry_(NULL), | 107 new_entry_(NULL), |
| 105 network_trans_(NULL), | 108 network_trans_(NULL), |
| 106 callback_(NULL), | 109 callback_(NULL), |
| 110 new_response_(NULL), | |
| 107 mode_(NONE), | 111 mode_(NONE), |
| 112 target_state_(STATE_NONE), | |
| 108 reading_(false), | 113 reading_(false), |
| 109 invalid_range_(false), | 114 invalid_range_(false), |
| 110 enable_range_support_(enable_range_support), | 115 enable_range_support_(enable_range_support), |
| 111 truncated_(false), | 116 truncated_(false), |
| 117 server_responded_206_(false), | |
| 112 read_offset_(0), | 118 read_offset_(0), |
| 113 effective_load_flags_(0), | 119 effective_load_flags_(0), |
| 114 final_upload_progress_(0), | 120 final_upload_progress_(0), |
| 115 ALLOW_THIS_IN_INITIALIZER_LIST( | 121 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 116 network_callback_(this, &Transaction::OnIOComplete)), | 122 network_callback_(this, &Transaction::OnIOComplete)), |
| 117 ALLOW_THIS_IN_INITIALIZER_LIST( | 123 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 118 cache_callback_(new CancelableCompletionCallback<Transaction>( | 124 cache_callback_(new CancelableCompletionCallback<Transaction>( |
| 119 this, &Transaction::OnIOComplete))) { | 125 this, &Transaction::OnIOComplete))) { |
| 120 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == | 126 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == |
| 121 ARRAYSIZE_UNSAFE(kValidationHeaders), | 127 ARRAYSIZE_UNSAFE(kValidationHeaders), |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 next_state_ = STATE_ENTRY_AVAILABLE; | 475 next_state_ = STATE_ENTRY_AVAILABLE; |
| 470 if (new_entry_) { | 476 if (new_entry_) { |
| 471 // We are inside AddTransactionToEntry() so avoid reentering DoLoop(). | 477 // We are inside AddTransactionToEntry() so avoid reentering DoLoop(). |
| 472 DCHECK_EQ(new_entry_, entry); | 478 DCHECK_EQ(new_entry_, entry); |
| 473 return OK; | 479 return OK; |
| 474 } | 480 } |
| 475 return DoLoop(OK); | 481 return DoLoop(OK); |
| 476 } | 482 } |
| 477 | 483 |
| 478 int HttpCache::Transaction::DoEntryAvailable() { | 484 int HttpCache::Transaction::DoEntryAvailable() { |
| 485 DCHECK(!new_entry_); | |
| 486 if (mode_ == WRITE) { | |
| 487 if (partial_.get()) | |
| 488 partial_->RestoreHeaders(&custom_request_->extra_headers); | |
| 489 next_state_ = STATE_SEND_REQUEST; | |
| 490 } else { | |
| 491 // We have to read the headers from the cached entry. | |
| 492 DCHECK(mode_ & READ_META); | |
| 493 next_state_ = STATE_CACHE_READ_RESPONSE; | |
| 494 } | |
| 495 return OK; | |
| 496 } | |
| 497 | |
| 498 int HttpCache::Transaction::DoCacheReadResponseComplete() { | |
| 479 // We now have access to the cache entry. | 499 // We now have access to the cache entry. |
| 480 // | 500 // |
| 481 // o if we are the writer for the transaction, then we can start the network | |
| 482 // transaction. | |
| 483 // | |
| 484 // o if we are a reader for the transaction, then we can start reading the | 501 // o if we are a reader for the transaction, then we can start reading the |
| 485 // cache entry. | 502 // cache entry. |
| 486 // | 503 // |
| 487 // o if we can read or write, then we should check if the cache entry needs | 504 // o if we can read or write, then we should check if the cache entry needs |
| 488 // to be validated and then issue a network request if needed or just read | 505 // to be validated and then issue a network request if needed or just read |
| 489 // from the cache if the cache entry is already valid. | 506 // from the cache if the cache entry is already valid. |
| 490 // | 507 // |
| 491 // o if we are set to UPDATE, then we are handling an externally | 508 // o if we are set to UPDATE, then we are handling an externally |
| 492 // conditionalized request (if-modified-since / if-none-match). We read | 509 // conditionalized request (if-modified-since / if-none-match). We check |
| 493 // the cache entry, and check if the request headers define a validation | 510 // if the request headers define a validation request. |
| 494 // request. | |
| 495 // | 511 // |
| 496 DCHECK(!new_entry_); | 512 int rv = OK; |
| 497 int rv; | |
| 498 switch (mode_) { | 513 switch (mode_) { |
| 499 case READ: | 514 case READ: |
| 500 rv = BeginCacheRead(); | 515 rv = BeginCacheRead(); |
| 501 break; | 516 break; |
| 502 case WRITE: | |
| 503 if (partial_.get()) | |
| 504 partial_->RestoreHeaders(&custom_request_->extra_headers); | |
| 505 next_state_ = STATE_SEND_REQUEST; | |
| 506 rv = OK; | |
| 507 break; | |
| 508 case READ_WRITE: | 517 case READ_WRITE: |
| 509 rv = BeginPartialCacheValidation(); | 518 rv = BeginPartialCacheValidation(); |
| 510 break; | 519 break; |
| 511 case UPDATE: | 520 case UPDATE: |
| 512 rv = BeginExternallyConditionalizedRequest(); | 521 rv = BeginExternallyConditionalizedRequest(); |
| 513 break; | 522 break; |
| 523 case WRITE: | |
| 514 default: | 524 default: |
| 515 NOTREACHED(); | 525 NOTREACHED(); |
| 516 rv = ERR_FAILED; | 526 rv = ERR_FAILED; |
| 517 } | 527 } |
| 518 return rv; | 528 return rv; |
| 519 } | 529 } |
| 520 | 530 |
| 521 bool HttpCache::Transaction::AddTruncatedFlag() { | 531 bool HttpCache::Transaction::AddTruncatedFlag() { |
| 522 DCHECK(mode_ & WRITE); | 532 DCHECK(mode_ & WRITE); |
| 523 | 533 |
| 524 // Don't set the flag for sparse entries. | 534 // Don't set the flag for sparse entries. |
| 525 if (partial_.get() && !truncated_) | 535 if (partial_.get() && !truncated_) |
| 526 return true; | 536 return true; |
| 527 | 537 |
| 528 // Double check that there is something worth keeping. | 538 // Double check that there is something worth keeping. |
| 529 if (!entry_->disk_entry->GetDataSize(kResponseContentIndex)) | 539 if (!entry_->disk_entry->GetDataSize(kResponseContentIndex)) |
| 530 return false; | 540 return false; |
| 531 | 541 |
| 542 // We have a serious problem here: We are inside the object destructor and | |
| 543 // we need to write to the cache. We could even have a pending operation in | |
| 544 // progress already so it's not that we can just issue another operation and | |
| 545 // cancel it immediately. So, for now, just verify that the operation | |
| 546 // completes synchronously. | |
| 532 truncated_ = true; | 547 truncated_ = true; |
| 533 WriteResponseInfoToEntry(true); | 548 target_state_ = STATE_NONE; |
| 549 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; | |
| 550 int rv = DoLoop(OK); | |
| 551 DCHECK_EQ(OK, rv); | |
| 534 return true; | 552 return true; |
| 535 } | 553 } |
| 536 | 554 |
| 537 void HttpCache::Transaction::DoCallback(int rv) { | 555 void HttpCache::Transaction::DoCallback(int rv) { |
| 538 DCHECK(rv != ERR_IO_PENDING); | 556 DCHECK(rv != ERR_IO_PENDING); |
| 539 DCHECK(callback_); | 557 DCHECK(callback_); |
| 540 | 558 |
| 541 // since Run may result in Read being called, clear callback_ up front. | 559 // Since Run may result in Read being called, clear callback_ up front. |
| 542 CompletionCallback* c = callback_; | 560 CompletionCallback* c = callback_; |
| 543 callback_ = NULL; | 561 callback_ = NULL; |
| 544 c->Run(rv); | 562 c->Run(rv); |
| 545 } | 563 } |
| 546 | 564 |
| 547 int HttpCache::Transaction::HandleResult(int rv) { | 565 int HttpCache::Transaction::HandleResult(int rv) { |
| 548 DCHECK(rv != ERR_IO_PENDING); | 566 DCHECK(rv != ERR_IO_PENDING); |
| 549 if (callback_) | 567 if (callback_) |
| 550 DoCallback(rv); | 568 DoCallback(rv); |
| 551 return rv; | 569 return rv; |
| 552 } | 570 } |
| 553 | 571 |
| 554 int HttpCache::Transaction::DoLoop(int result) { | 572 int HttpCache::Transaction::DoLoop(int result) { |
| 555 DCHECK(next_state_ != STATE_NONE); | 573 DCHECK(next_state_ != STATE_NONE); |
| 556 | 574 |
| 557 int rv = result; | 575 int rv = result; |
| 558 do { | 576 do { |
| 559 State state = next_state_; | 577 State state = next_state_; |
| 560 next_state_ = STATE_NONE; | 578 next_state_ = STATE_NONE; |
| 561 switch (state) { | 579 switch (state) { |
| 562 case STATE_SEND_REQUEST: | 580 case STATE_SEND_REQUEST: |
| 563 DCHECK_EQ(OK, rv); | 581 DCHECK_EQ(OK, rv); |
| 564 rv = DoSendRequest(); | 582 rv = DoSendRequest(); |
| 565 break; | 583 break; |
| 566 case STATE_SEND_REQUEST_COMPLETE: | 584 case STATE_SEND_REQUEST_COMPLETE: |
| 567 rv = DoSendRequestComplete(rv); | 585 rv = DoSendRequestComplete(rv); |
| 568 break; | 586 break; |
| 587 case STATE_SUCCESSFUL_SEND_REQUEST: | |
| 588 DCHECK_EQ(OK, rv); | |
| 589 rv = DoSuccessfulSendRequest(); | |
| 590 break; | |
| 569 case STATE_NETWORK_READ: | 591 case STATE_NETWORK_READ: |
| 570 DCHECK_EQ(OK, rv); | 592 DCHECK_EQ(OK, rv); |
| 571 rv = DoNetworkRead(); | 593 rv = DoNetworkRead(); |
| 572 break; | 594 break; |
| 573 case STATE_NETWORK_READ_COMPLETE: | 595 case STATE_NETWORK_READ_COMPLETE: |
| 574 rv = DoNetworkReadComplete(rv); | 596 rv = DoNetworkReadComplete(rv); |
| 575 break; | 597 break; |
| 576 case STATE_INIT_ENTRY: | 598 case STATE_INIT_ENTRY: |
| 577 DCHECK_EQ(OK, rv); | 599 DCHECK_EQ(OK, rv); |
| 578 rv = DoInitEntry(); | 600 rv = DoInitEntry(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 606 rv = DoAddToEntry(); | 628 rv = DoAddToEntry(); |
| 607 break; | 629 break; |
| 608 case STATE_ENTRY_AVAILABLE: | 630 case STATE_ENTRY_AVAILABLE: |
| 609 DCHECK_EQ(OK, rv); | 631 DCHECK_EQ(OK, rv); |
| 610 rv = DoEntryAvailable(); | 632 rv = DoEntryAvailable(); |
| 611 break; | 633 break; |
| 612 case STATE_PARTIAL_CACHE_VALIDATION: | 634 case STATE_PARTIAL_CACHE_VALIDATION: |
| 613 DCHECK_EQ(OK, rv); | 635 DCHECK_EQ(OK, rv); |
| 614 rv = DoPartialCacheValidation(); | 636 rv = DoPartialCacheValidation(); |
| 615 break; | 637 break; |
| 638 case STATE_UPDATE_CACHED_RESPONSE: | |
| 639 DCHECK_EQ(OK, rv); | |
| 640 rv = DoUpdateCachedResponse(); | |
| 641 break; | |
| 642 case STATE_UPDATE_CACHED_RESPONSE_COMPLETE: | |
| 643 rv = DoUpdateCachedResponseComplete(rv); | |
| 644 break; | |
| 645 case STATE_OVERWRITE_CACHED_RESPONSE: | |
| 646 DCHECK_EQ(OK, rv); | |
| 647 rv = DoOverwriteCachedResponse(); | |
| 648 break; | |
| 649 case STATE_TRUNCATE_CACHED_DATA: | |
| 650 DCHECK_EQ(OK, rv); | |
| 651 rv = DoTruncateCachedData(); | |
| 652 break; | |
| 653 case STATE_TRUNCATE_CACHED_DATA_COMPLETE: | |
| 654 rv = DoTruncateCachedDataComplete(rv); | |
| 655 break; | |
| 656 case STATE_PARTIAL_HEADERS_RECEIVED: | |
| 657 DCHECK_EQ(OK, rv); | |
| 658 rv = DoPartialHeadersReceived(); | |
| 659 break; | |
| 660 case STATE_CACHE_READ_RESPONSE: | |
| 661 DCHECK_EQ(OK, rv); | |
| 662 rv = DoCacheReadResponse(); | |
| 663 break; | |
| 664 case STATE_CACHE_READ_RESPONSE_COMPLETE: | |
| 665 DCHECK_EQ(OK, rv); | |
| 666 rv = DoCacheReadResponseComplete(); | |
| 667 break; | |
| 668 case STATE_CACHE_WRITE_RESPONSE: | |
| 669 DCHECK_EQ(OK, rv); | |
| 670 rv = DoCacheWriteResponse(); | |
| 671 break; | |
| 672 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: | |
| 673 DCHECK_EQ(OK, rv); | |
| 674 rv = DoCacheWriteTruncatedResponse(); | |
| 675 break; | |
| 676 case STATE_CACHE_WRITE_RESPONSE_COMPLETE: | |
| 677 rv = DoCacheWriteResponseComplete(rv); | |
| 678 break; | |
| 616 case STATE_CACHE_QUERY_DATA: | 679 case STATE_CACHE_QUERY_DATA: |
| 617 DCHECK_EQ(OK, rv); | 680 DCHECK_EQ(OK, rv); |
| 618 rv = DoCacheQueryData(); | 681 rv = DoCacheQueryData(); |
| 619 break; | 682 break; |
| 620 case STATE_CACHE_QUERY_DATA_COMPLETE: | 683 case STATE_CACHE_QUERY_DATA_COMPLETE: |
| 621 rv = DoCacheQueryDataComplete(rv); | 684 rv = DoCacheQueryDataComplete(rv); |
| 622 break; | 685 break; |
| 623 case STATE_CACHE_READ_DATA: | 686 case STATE_CACHE_READ_DATA: |
| 624 DCHECK_EQ(OK, rv); | 687 DCHECK_EQ(OK, rv); |
| 625 rv = DoCacheReadData(); | 688 rv = DoCacheReadData(); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 782 | 845 |
| 783 if (request_->method == "POST" && | 846 if (request_->method == "POST" && |
| 784 request_->upload_data && request_->upload_data->identifier()) | 847 request_->upload_data && request_->upload_data->identifier()) |
| 785 return false; | 848 return false; |
| 786 | 849 |
| 787 // TODO(darin): add support for caching HEAD responses | 850 // TODO(darin): add support for caching HEAD responses |
| 788 return true; | 851 return true; |
| 789 } | 852 } |
| 790 | 853 |
| 791 int HttpCache::Transaction::BeginCacheRead() { | 854 int HttpCache::Transaction::BeginCacheRead() { |
| 792 DCHECK(mode_ == READ); | |
| 793 | |
| 794 // Read response headers. | |
| 795 int rv = ReadResponseInfoFromEntry(); | |
| 796 if (rv != OK) | |
| 797 return rv; | |
| 798 | |
| 799 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. | 855 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. |
| 800 if (response_.headers->response_code() == 206 || partial_.get()) { | 856 if (response_.headers->response_code() == 206 || partial_.get()) { |
| 801 NOTREACHED(); | 857 NOTREACHED(); |
| 802 return ERR_CACHE_MISS; | 858 return ERR_CACHE_MISS; |
| 803 } | 859 } |
| 804 | 860 |
| 805 // We don't have the whole resource. | 861 // We don't have the whole resource. |
| 806 if (truncated_) | 862 if (truncated_) |
| 807 return ERR_CACHE_MISS; | 863 return ERR_CACHE_MISS; |
| 808 | 864 |
| 809 return rv; | 865 return OK; |
| 810 } | 866 } |
| 811 | 867 |
| 812 int HttpCache::Transaction::BeginCacheValidation() { | 868 int HttpCache::Transaction::BeginCacheValidation() { |
| 813 DCHECK(mode_ == READ_WRITE); | 869 DCHECK(mode_ == READ_WRITE); |
| 814 | 870 |
| 815 if ((effective_load_flags_ & LOAD_PREFERRING_CACHE || | 871 if ((effective_load_flags_ & LOAD_PREFERRING_CACHE || |
| 816 !RequiresValidation()) && !partial_.get()) { | 872 !RequiresValidation()) && !partial_.get()) { |
| 817 cache_->ConvertWriterToReader(entry_); | 873 cache_->ConvertWriterToReader(entry_); |
| 818 mode_ = READ; | 874 mode_ = READ; |
| 819 } else { | 875 } else { |
| 820 // Make the network request conditional, to see if we may reuse our cached | 876 // Make the network request conditional, to see if we may reuse our cached |
| 821 // response. If we cannot do so, then we just resort to a normal fetch. | 877 // response. If we cannot do so, then we just resort to a normal fetch. |
| 822 // Our mode remains READ_WRITE for a conditional request. We'll switch to | 878 // Our mode remains READ_WRITE for a conditional request. We'll switch to |
| 823 // either READ or WRITE mode once we hear back from the server. | 879 // either READ or WRITE mode once we hear back from the server. |
| 824 if (!ConditionalizeRequest()) | 880 if (!ConditionalizeRequest()) |
| 825 mode_ = WRITE; | 881 mode_ = WRITE; |
| 826 next_state_ = STATE_SEND_REQUEST; | 882 next_state_ = STATE_SEND_REQUEST; |
| 827 } | 883 } |
| 828 return OK; | 884 return OK; |
| 829 } | 885 } |
| 830 | 886 |
| 831 int HttpCache::Transaction::BeginPartialCacheValidation() { | 887 int HttpCache::Transaction::BeginPartialCacheValidation() { |
| 832 DCHECK(mode_ == READ_WRITE); | 888 DCHECK(mode_ == READ_WRITE); |
| 833 | 889 |
| 834 int rv = ReadResponseInfoFromEntry(); | |
| 835 if (rv != OK) { | |
| 836 DCHECK(rv != ERR_IO_PENDING); | |
| 837 return rv; | |
| 838 } | |
| 839 | |
| 840 if (response_.headers->response_code() != 206 && !partial_.get() && | 890 if (response_.headers->response_code() != 206 && !partial_.get() && |
| 841 !truncated_) | 891 !truncated_) |
| 842 return BeginCacheValidation(); | 892 return BeginCacheValidation(); |
| 843 | 893 |
| 844 if (!enable_range_support_) | 894 if (!enable_range_support_) |
| 845 return BeginCacheValidation(); | 895 return BeginCacheValidation(); |
| 846 | 896 |
| 847 bool byte_range_requested = partial_.get() != NULL; | 897 bool byte_range_requested = partial_.get() != NULL; |
| 848 if (byte_range_requested) { | 898 if (byte_range_requested) { |
| 849 next_state_ = STATE_CACHE_QUERY_DATA; | 899 next_state_ = STATE_CACHE_QUERY_DATA; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 930 return OK; | 980 return OK; |
| 931 } | 981 } |
| 932 | 982 |
| 933 return BeginCacheValidation(); | 983 return BeginCacheValidation(); |
| 934 } | 984 } |
| 935 | 985 |
| 936 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { | 986 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { |
| 937 DCHECK_EQ(UPDATE, mode_); | 987 DCHECK_EQ(UPDATE, mode_); |
| 938 DCHECK(external_validation_.initialized); | 988 DCHECK(external_validation_.initialized); |
| 939 | 989 |
| 940 // Read the cached response. | |
| 941 int rv = ReadResponseInfoFromEntry(); | |
| 942 if (rv != OK) { | |
| 943 DCHECK(rv != ERR_IO_PENDING); | |
| 944 return rv; | |
| 945 } | |
| 946 | |
| 947 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) { | 990 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) { |
| 948 if (external_validation_.values[i].empty()) | 991 if (external_validation_.values[i].empty()) |
| 949 continue; | 992 continue; |
| 950 // Retrieve either the cached response's "etag" or "last-modified" header. | 993 // Retrieve either the cached response's "etag" or "last-modified" header. |
| 951 std::string validator; | 994 std::string validator; |
| 952 response_.headers->EnumerateHeader( | 995 response_.headers->EnumerateHeader( |
| 953 NULL, | 996 NULL, |
| 954 kValidationHeaders[i].related_response_header_name, | 997 kValidationHeaders[i].related_response_header_name, |
| 955 &validator); | 998 &validator); |
| 956 | 999 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1245 if (partial_.get()) { | 1288 if (partial_.get()) { |
| 1246 return partial_->CacheRead(entry_->disk_entry, read_buf_, read_buf_len_, | 1289 return partial_->CacheRead(entry_->disk_entry, read_buf_, read_buf_len_, |
| 1247 cache_callback_); | 1290 cache_callback_); |
| 1248 } | 1291 } |
| 1249 | 1292 |
| 1250 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, | 1293 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, |
| 1251 read_buf_, read_buf_len_, | 1294 read_buf_, read_buf_len_, |
| 1252 cache_callback_); | 1295 cache_callback_); |
| 1253 } | 1296 } |
| 1254 | 1297 |
| 1255 int HttpCache::Transaction::ReadResponseInfoFromEntry() { | 1298 int HttpCache::Transaction::DoCacheReadResponse() { |
| 1256 DCHECK(entry_); | 1299 DCHECK(entry_); |
| 1300 next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE; | |
| 1257 | 1301 |
| 1258 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_READ_INFO); | 1302 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_READ_INFO); |
| 1259 bool read_ok = | 1303 bool read_ok = |
| 1260 HttpCache::ReadResponseInfo(entry_->disk_entry, &response_, &truncated_); | 1304 HttpCache::ReadResponseInfo(entry_->disk_entry, &response_, &truncated_); |
| 1261 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_READ_INFO); | 1305 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_READ_INFO); |
| 1262 | 1306 |
| 1263 return read_ok ? OK : ERR_CACHE_READ_FAILURE; | 1307 return read_ok ? OK : ERR_CACHE_READ_FAILURE; |
| 1264 } | 1308 } |
| 1265 | 1309 |
| 1266 int HttpCache::Transaction::WriteToEntry(int index, int offset, | 1310 int HttpCache::Transaction::WriteToEntry(int index, int offset, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1281 DLOG(ERROR) << "failed to write response data to cache"; | 1325 DLOG(ERROR) << "failed to write response data to cache"; |
| 1282 DoneWritingToEntry(false); | 1326 DoneWritingToEntry(false); |
| 1283 | 1327 |
| 1284 // We want to ignore errors writing to disk and just keep reading from | 1328 // We want to ignore errors writing to disk and just keep reading from |
| 1285 // the network. | 1329 // the network. |
| 1286 rv = data_len; | 1330 rv = data_len; |
| 1287 } | 1331 } |
| 1288 return rv; | 1332 return rv; |
| 1289 } | 1333 } |
| 1290 | 1334 |
| 1291 void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { | 1335 int HttpCache::Transaction::DoCacheWriteResponse() { |
| 1336 return WriteResponseInfoToEntry(false); | |
| 1337 } | |
| 1338 | |
| 1339 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { | |
| 1340 return WriteResponseInfoToEntry(true); | |
| 1341 } | |
| 1342 | |
| 1343 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { | |
| 1344 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; | |
| 1292 if (!entry_) | 1345 if (!entry_) |
| 1293 return; | 1346 return OK; |
| 1294 | 1347 |
| 1295 // Do not cache no-store content (unless we are record mode). Do not cache | 1348 // Do not cache no-store content (unless we are record mode). Do not cache |
| 1296 // content with cert errors either. This is to prevent not reporting net | 1349 // content with cert errors either. This is to prevent not reporting net |
| 1297 // errors when loading a resource from the cache. When we load a page over | 1350 // errors when loading a resource from the cache. When we load a page over |
| 1298 // HTTPS with a cert error we show an SSL blocking page. If the user clicks | 1351 // HTTPS with a cert error we show an SSL blocking page. If the user clicks |
| 1299 // proceed we reload the resource ignoring the errors. The loaded resource | 1352 // proceed we reload the resource ignoring the errors. The loaded resource |
| 1300 // is then cached. If that resource is subsequently loaded from the cache, | 1353 // is then cached. If that resource is subsequently loaded from the cache, |
| 1301 // no net error is reported (even though the cert status contains the actual | 1354 // no net error is reported (even though the cert status contains the actual |
| 1302 // errors) and no SSL blocking page is shown. An alternative would be to | 1355 // errors) and no SSL blocking page is shown. An alternative would be to |
| 1303 // reverse-map the cert status to a net error and replay the net error. | 1356 // reverse-map the cert status to a net error and replay the net error. |
| 1304 if ((cache_->mode() != RECORD && | 1357 if ((cache_->mode() != RECORD && |
| 1305 response_.headers->HasHeaderValue("cache-control", "no-store")) || | 1358 response_.headers->HasHeaderValue("cache-control", "no-store")) || |
| 1306 net::IsCertStatusError(response_.ssl_info.cert_status)) { | 1359 net::IsCertStatusError(response_.ssl_info.cert_status)) { |
| 1307 DoneWritingToEntry(false); | 1360 DoneWritingToEntry(false); |
| 1308 return; | 1361 return OK; |
| 1309 } | 1362 } |
| 1310 | 1363 |
| 1311 // When writing headers, we normally only write the non-transient | 1364 // When writing headers, we normally only write the non-transient |
| 1312 // headers; when in record mode, record everything. | 1365 // headers; when in record mode, record everything. |
| 1313 bool skip_transient_headers = (cache_->mode() != RECORD); | 1366 bool skip_transient_headers = (cache_->mode() != RECORD); |
| 1314 | 1367 |
| 1315 if (truncated) { | 1368 if (truncated) { |
| 1316 DCHECK_EQ(200, response_.headers->response_code()); | 1369 DCHECK_EQ(200, response_.headers->response_code()); |
| 1317 } | 1370 } |
| 1318 | 1371 |
| 1319 if (!HttpCache::WriteResponseInfo(entry_->disk_entry, &response_, | 1372 if (!HttpCache::WriteResponseInfo(entry_->disk_entry, &response_, |
| 1320 skip_transient_headers, truncated)) { | 1373 skip_transient_headers, truncated)) { |
| 1321 DLOG(ERROR) << "failed to write response info to cache"; | 1374 DLOG(ERROR) << "failed to write response info to cache"; |
| 1322 DoneWritingToEntry(false); | 1375 DoneWritingToEntry(false); |
| 1323 } | 1376 } |
| 1377 return OK; | |
| 1378 } | |
| 1379 | |
| 1380 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { | |
| 1381 next_state_ = target_state_; | |
| 1382 target_state_ = STATE_NONE; | |
| 1383 return OK; | |
| 1324 } | 1384 } |
| 1325 | 1385 |
| 1326 int HttpCache::Transaction::AppendResponseDataToEntry( | 1386 int HttpCache::Transaction::AppendResponseDataToEntry( |
| 1327 IOBuffer* data, int data_len, CompletionCallback* callback) { | 1387 IOBuffer* data, int data_len, CompletionCallback* callback) { |
| 1328 if (!entry_ || !data_len) | 1388 if (!entry_ || !data_len) |
| 1329 return data_len; | 1389 return data_len; |
| 1330 | 1390 |
| 1331 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); | 1391 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); |
| 1332 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, | 1392 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, |
| 1333 callback); | 1393 callback); |
| 1334 } | 1394 } |
| 1335 | 1395 |
| 1336 void HttpCache::Transaction::TruncateResponseData() { | 1396 int HttpCache::Transaction::DoTruncateCachedData() { |
| 1397 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; | |
| 1337 if (!entry_) | 1398 if (!entry_) |
| 1338 return; | 1399 return OK; |
| 1339 | 1400 |
| 1340 // Truncate the stream. | 1401 // Truncate the stream. |
| 1341 int rv = WriteToEntry(kResponseContentIndex, 0, NULL, 0, NULL); | 1402 int rv = WriteToEntry(kResponseContentIndex, 0, NULL, 0, NULL); |
| 1342 DCHECK(rv != ERR_IO_PENDING); | 1403 DCHECK(rv != ERR_IO_PENDING); |
| 1404 return OK; | |
| 1343 } | 1405 } |
| 1344 | 1406 |
| 1345 void HttpCache::Transaction::DoneWritingToEntry(bool success) { | 1407 void HttpCache::Transaction::DoneWritingToEntry(bool success) { |
| 1346 if (!entry_) | 1408 if (!entry_) |
| 1347 return; | 1409 return; |
| 1348 | 1410 |
| 1349 if (cache_->mode() == RECORD) | 1411 if (cache_->mode() == RECORD) |
| 1350 DLOG(INFO) << "Recorded: " << request_->method << request_->url | 1412 DLOG(INFO) << "Recorded: " << request_->method << request_->url |
| 1351 << " status: " << response_.headers->response_code(); | 1413 << " status: " << response_.headers->response_code(); |
| 1352 | 1414 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1430 | 1492 |
| 1431 if (partial_.get()) | 1493 if (partial_.get()) |
| 1432 return DoPartialNetworkReadCompleted(result); | 1494 return DoPartialNetworkReadCompleted(result); |
| 1433 | 1495 |
| 1434 if (result == 0) // End of file. | 1496 if (result == 0) // End of file. |
| 1435 DoneWritingToEntry(true); | 1497 DoneWritingToEntry(true); |
| 1436 | 1498 |
| 1437 return result; | 1499 return result; |
| 1438 } | 1500 } |
| 1439 | 1501 |
| 1502 // We received the response headers and there is no error. | |
| 1503 int HttpCache::Transaction::DoSuccessfulSendRequest() { | |
| 1504 DCHECK(!new_response_); | |
| 1505 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); | |
| 1506 if (new_response->headers->response_code() == 401 || | |
| 1507 new_response->headers->response_code() == 407) { | |
| 1508 auth_response_ = *new_response; | |
| 1509 return OK; | |
| 1510 } | |
| 1511 | |
| 1512 if (!ValidatePartialResponse(new_response->headers, &server_responded_206_) && | |
| 1513 !auth_response_.headers) { | |
| 1514 // Something went wrong with this request and we have to restart it. | |
| 1515 // If we have an authentication response, we are exposed to weird things | |
| 1516 // hapenning if the user cancels the authentication before we receive | |
| 1517 // the new response. | |
| 1518 response_ = HttpResponseInfo(); | |
| 1519 network_trans_.reset(); | |
| 1520 next_state_ = STATE_SEND_REQUEST; | |
| 1521 return OK; | |
| 1522 } | |
| 1523 if (server_responded_206_ && mode_ == READ_WRITE && !truncated_ && | |
| 1524 response_.headers->response_code() == 200) { | |
| 1525 // We have stored the full entry, but it changed and the server is | |
| 1526 // sending a range. We have to delete the old entry. | |
| 1527 DoneWritingToEntry(false); | |
| 1528 } | |
| 1529 | |
| 1530 new_response_ = new_response; | |
| 1531 // Are we expecting a response to a conditional query? | |
| 1532 if (mode_ == READ_WRITE || mode_ == UPDATE) { | |
| 1533 if (new_response->headers->response_code() == 304 || | |
| 1534 server_responded_206_) { | |
| 1535 next_state_ = STATE_UPDATE_CACHED_RESPONSE; | |
| 1536 return OK; | |
| 1537 } | |
| 1538 mode_ = WRITE; | |
| 1539 } | |
| 1540 | |
| 1541 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; | |
| 1542 return OK; | |
| 1543 } | |
| 1544 | |
| 1545 // We received 304 or 206 and we want to update the cached response headers. | |
| 1546 int HttpCache::Transaction::DoUpdateCachedResponse() { | |
| 1547 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; | |
| 1548 int rv = OK; | |
| 1549 // Update cached response based on headers in new_response. | |
| 1550 // TODO(wtc): should we update cached certificate (response_.ssl_info), too? | |
| 1551 response_.headers->Update(*new_response_->headers); | |
| 1552 response_.response_time = new_response_->response_time; | |
| 1553 response_.request_time = new_response_->request_time; | |
| 1554 | |
| 1555 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { | |
| 1556 cache_->DoomEntry(cache_key_); | |
| 1557 } else { | |
| 1558 // If we are already reading, we already updated the headers for this | |
| 1559 // request; doing it again will change Content-Length. | |
| 1560 if (!reading_) { | |
| 1561 target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; | |
| 1562 next_state_ = STATE_CACHE_WRITE_RESPONSE; | |
| 1563 rv = OK; | |
| 1564 } | |
| 1565 } | |
| 1566 return rv; | |
| 1567 } | |
| 1568 | |
| 1569 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { | |
| 1570 if (mode_ == UPDATE) { | |
| 1571 DCHECK(!server_responded_206_); | |
| 1572 // We got a "not modified" response and already updated the corresponding | |
| 1573 // cache entry above. | |
| 1574 // | |
| 1575 // By closing the cached entry now, we make sure that the 304 rather than | |
| 1576 // the cached 200 response, is what will be returned to the user. | |
| 1577 DoneWritingToEntry(true); | |
| 1578 } else if (entry_ && !server_responded_206_) { | |
| 1579 DCHECK_EQ(READ_WRITE, mode_); | |
| 1580 if (!partial_.get() || partial_->IsLastRange()) { | |
| 1581 cache_->ConvertWriterToReader(entry_); | |
| 1582 mode_ = READ; | |
| 1583 } | |
| 1584 // We no longer need the network transaction, so destroy it. | |
| 1585 final_upload_progress_ = network_trans_->GetUploadProgress(); | |
| 1586 network_trans_.reset(); | |
| 1587 } | |
| 1588 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; | |
| 1589 return OK; | |
| 1590 } | |
| 1591 | |
| 1592 int HttpCache::Transaction::DoOverwriteCachedResponse() { | |
| 1593 if (mode_ & READ) { | |
| 1594 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; | |
| 1595 return OK; | |
| 1596 } | |
| 1597 | |
| 1598 // We change the value of Content-Length for partial content. | |
| 1599 if (server_responded_206_ && partial_.get()) | |
| 1600 partial_->FixContentLength(new_response_->headers); | |
| 1601 | |
| 1602 response_ = *new_response_; | |
| 1603 target_state_ = STATE_TRUNCATE_CACHED_DATA; | |
| 1604 next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE : | |
| 1605 STATE_CACHE_WRITE_RESPONSE; | |
| 1606 return OK; | |
| 1607 } | |
| 1608 | |
| 1609 int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) { | |
| 1610 // If this response is a redirect, then we can stop writing now. (We don't | |
| 1611 // need to cache the response body of a redirect.) | |
| 1612 if (response_.headers->IsRedirect(NULL)) | |
| 1613 DoneWritingToEntry(true); | |
| 1614 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; | |
| 1615 return OK; | |
| 1616 } | |
| 1617 | |
| 1618 int HttpCache::Transaction::DoPartialHeadersReceived() { | |
| 1619 new_response_ = NULL; | |
| 1620 if (!partial_.get()) | |
| 1621 return OK; | |
| 1622 | |
| 1623 if (reading_) { | |
| 1624 if (network_trans_.get()) { | |
| 1625 next_state_ = STATE_NETWORK_READ; | |
| 1626 } else { | |
| 1627 next_state_ = STATE_CACHE_READ_DATA; | |
| 1628 } | |
| 1629 } else if (mode_ != NONE) { | |
| 1630 // We are about to return the headers for a byte-range request to the user, | |
| 1631 // so let's fix them. | |
| 1632 partial_->FixResponseHeaders(response_.headers); | |
| 1633 } | |
| 1634 return OK; | |
| 1635 } | |
| 1636 | |
| 1440 int HttpCache::Transaction::DoSendRequestComplete(int result) { | 1637 int HttpCache::Transaction::DoSendRequestComplete(int result) { |
| 1441 if (!cache_) | 1638 if (!cache_) |
| 1442 return ERR_UNEXPECTED; | 1639 return ERR_UNEXPECTED; |
| 1443 | 1640 |
| 1444 if (result == OK) { | 1641 if (result == OK) { |
| 1445 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); | 1642 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; |
| 1446 if (new_response->headers->response_code() == 401 || | 1643 return OK; |
| 1447 new_response->headers->response_code() == 407) { | 1644 } |
| 1448 auth_response_ = *new_response; | |
| 1449 } else { | |
| 1450 bool partial_content; | |
| 1451 if (!ValidatePartialResponse(new_response->headers, &partial_content) && | |
| 1452 !auth_response_.headers) { | |
| 1453 // Something went wrong with this request and we have to restart it. | |
| 1454 // If we have an authentication response, we are exposed to weird things | |
| 1455 // hapenning if the user cancels the authentication before we receive | |
| 1456 // the new response. | |
| 1457 response_ = HttpResponseInfo(); | |
| 1458 network_trans_.reset(); | |
| 1459 next_state_ = STATE_SEND_REQUEST; | |
| 1460 return OK; | |
| 1461 } | |
| 1462 if (partial_content && mode_ == READ_WRITE && !truncated_ && | |
| 1463 response_.headers->response_code() == 200) { | |
| 1464 // We have stored the full entry, but it changed and the server is | |
| 1465 // sending a range. We have to delete the old entry. | |
| 1466 DoneWritingToEntry(false); | |
| 1467 } | |
| 1468 | 1645 |
| 1469 // Are we expecting a response to a conditional query? | 1646 if (IsCertificateError(result)) { |
| 1470 if (mode_ == READ_WRITE || mode_ == UPDATE) { | |
| 1471 if (new_response->headers->response_code() == 304 || partial_content) { | |
| 1472 // Update cached response based on headers in new_response. | |
| 1473 // TODO(wtc): should we update cached certificate | |
| 1474 // (response_.ssl_info), too? | |
| 1475 response_.headers->Update(*new_response->headers); | |
| 1476 response_.response_time = new_response->response_time; | |
| 1477 response_.request_time = new_response->request_time; | |
| 1478 | |
| 1479 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { | |
| 1480 cache_->DoomEntry(cache_key_); | |
| 1481 } else { | |
| 1482 // If we are already reading, we already updated the headers for | |
| 1483 // this request; doing it again will change Content-Length. | |
| 1484 if (!reading_) | |
| 1485 WriteResponseInfoToEntry(false); | |
| 1486 } | |
| 1487 | |
| 1488 if (mode_ == UPDATE) { | |
| 1489 DCHECK(!partial_content); | |
| 1490 // We got a "not modified" response and already updated the | |
| 1491 // corresponding cache entry above. | |
| 1492 // | |
| 1493 // By closing the cached entry now, we make sure that the | |
| 1494 // 304 rather than the cached 200 response, is what will be | |
| 1495 // returned to the user. | |
| 1496 DoneWritingToEntry(true); | |
| 1497 } else if (entry_ && !partial_content) { | |
| 1498 DCHECK_EQ(READ_WRITE, mode_); | |
| 1499 if (!partial_.get() || partial_->IsLastRange()) { | |
| 1500 cache_->ConvertWriterToReader(entry_); | |
| 1501 mode_ = READ; | |
| 1502 } | |
| 1503 // We no longer need the network transaction, so destroy it. | |
| 1504 final_upload_progress_ = network_trans_->GetUploadProgress(); | |
| 1505 network_trans_.reset(); | |
| 1506 } | |
| 1507 } else { | |
| 1508 mode_ = WRITE; | |
| 1509 } | |
| 1510 } | |
| 1511 | |
| 1512 if (!(mode_ & READ)) { | |
| 1513 // We change the value of Content-Length for partial content. | |
| 1514 if (partial_content && partial_.get()) | |
| 1515 partial_->FixContentLength(new_response->headers); | |
| 1516 | |
| 1517 response_ = *new_response; | |
| 1518 WriteResponseInfoToEntry(truncated_); | |
| 1519 | |
| 1520 // Truncate response data. | |
| 1521 TruncateResponseData(); | |
| 1522 | |
| 1523 // If this response is a redirect, then we can stop writing now. (We | |
| 1524 // don't need to cache the response body of a redirect.) | |
| 1525 if (response_.headers->IsRedirect(NULL)) | |
| 1526 DoneWritingToEntry(true); | |
| 1527 } | |
| 1528 if (reading_ && partial_.get()) { | |
| 1529 if (network_trans_.get()) { | |
| 1530 next_state_ = STATE_NETWORK_READ; | |
| 1531 } else { | |
| 1532 next_state_ = STATE_CACHE_READ_DATA; | |
| 1533 } | |
| 1534 result = OK; | |
| 1535 } else if (mode_ != NONE && partial_.get()) { | |
| 1536 // We are about to return the headers for a byte-range request to the | |
| 1537 // user, so let's fix them. | |
| 1538 partial_->FixResponseHeaders(response_.headers); | |
| 1539 } | |
| 1540 } | |
| 1541 } else if (IsCertificateError(result)) { | |
| 1542 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); | 1647 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); |
| 1543 // If we get a certificate error, then there is a certificate in ssl_info, | 1648 // If we get a certificate error, then there is a certificate in ssl_info, |
| 1544 // so GetResponseInfo() should never returns NULL here. | 1649 // so GetResponseInfo() should never returns NULL here. |
| 1545 DCHECK(response); | 1650 DCHECK(response); |
| 1546 response_.ssl_info = response->ssl_info; | 1651 response_.ssl_info = response->ssl_info; |
| 1547 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 1652 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
| 1548 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); | 1653 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); |
| 1549 DCHECK(response); | 1654 DCHECK(response); |
| 1550 response_.cert_request_info = response->cert_request_info; | 1655 response_.cert_request_info = response->cert_request_info; |
| 1551 } | 1656 } |
| 1552 return result; | 1657 return result; |
| 1553 } | 1658 } |
| 1554 | 1659 |
| 1555 void HttpCache::Transaction::OnIOComplete(int result) { | 1660 void HttpCache::Transaction::OnIOComplete(int result) { |
| 1556 DoLoop(result); | 1661 DoLoop(result); |
| 1557 } | 1662 } |
| 1558 | 1663 |
| 1559 } // namespace net | 1664 } // namespace net |
| OLD | NEW |