1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/http/http_cache_transaction.h" 6 7 #include "build/build_config.h" 8 9 #if defined(OS_POSIX) 10 #include <unistd.h> 11 #endif 12 13 #include <string> 14 15 #include "base/compiler_specific.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/metrics/field_trial.h" 18 #include "base/metrics/histogram.h" 19 #include "base/string_util.h" 20 #include "base/time.h" 21 #include "net/base/cert_status_flags.h" 22 #include "net/base/io_buffer.h" 23 #include "net/base/load_flags.h" 24 #include "net/base/net_errors.h" 25 #include "net/base/net_log.h" 26 #include "net/base/network_delegate.h" 27 #include "net/base/ssl_cert_request_info.h" 28 #include "net/base/ssl_config_service.h" 29 #include "net/disk_cache/disk_cache.h" 30 #include "net/http/disk_cache_based_ssl_host_info.h" 31 #include "net/http/http_network_session.h" 32 #include "net/http/http_request_info.h" 33 #include "net/http/http_response_headers.h" 34 #include "net/http/http_transaction.h" 35 #include "net/http/http_util.h" 36 #include "net/http/partial_data.h" 37 38 using base::Time; 39 40 namespace net { 41 42 struct HeaderNameAndValue { 43 const char* name; 44 const char* value; 45 }; 46 47 // If the request includes one of these request headers, then avoid caching 48 // to avoid getting confused. 49 static const HeaderNameAndValue kPassThroughHeaders[] = { 50 { "if-unmodified-since", NULL }, // causes unexpected 412s 51 { "if-match", NULL }, // causes unexpected 412s 52 { "if-range", NULL }, 53 { NULL, NULL } 54 }; 55 56 struct ValidationHeaderInfo { 57 const char* request_header_name; 58 const char* related_response_header_name; 59 }; 60 61 static const ValidationHeaderInfo kValidationHeaders[] = { 62 { "if-modified-since", "last-modified" }, 63 { "if-none-match", "etag" }, 64 }; 65 66 // If the request includes one of these request headers, then avoid reusing 67 // our cached copy if any. 68 static const HeaderNameAndValue kForceFetchHeaders[] = { 69 { "cache-control", "no-cache" }, 70 { "pragma", "no-cache" }, 71 { NULL, NULL } 72 }; 73 74 // If the request includes one of these request headers, then force our 75 // cached copy (if any) to be revalidated before reusing it. 76 static const HeaderNameAndValue kForceValidateHeaders[] = { 77 { "cache-control", "max-age=0" }, 78 { NULL, NULL } 79 }; 80 81 static bool HeaderMatches(const HttpRequestHeaders& headers, 82 const HeaderNameAndValue* search) { 83 for (; search->name; ++search) { 84 std::string header_value; 85 if (!headers.GetHeader(search->name, &header_value)) 86 continue; 87 88 if (!search->value) 89 return true; 90 91 HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ','); 92 while (v.GetNext()) { 93 if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value)) 94 return true; 95 } 96 } 97 return false; 98 } 99 100 //----------------------------------------------------------------------------- 101 102 HttpCache::Transaction::Transaction(HttpCache* cache) 103 : next_state_(STATE_NONE), 104 request_(NULL), 105 cache_(cache->AsWeakPtr()), 106 entry_(NULL), 107 new_entry_(NULL), 108 network_trans_(NULL), 109 callback_(NULL), 110 new_response_(NULL), 111 mode_(NONE), 112 target_state_(STATE_NONE), 113 reading_(false), 114 invalid_range_(false), 115 truncated_(false), 116 is_sparse_(false), 117 server_responded_206_(false), 118 cache_pending_(false), 119 read_offset_(0), 120 effective_load_flags_(0), 121 write_len_(0), 122 final_upload_progress_(0), 123 ALLOW_THIS_IN_INITIALIZER_LIST( 124 io_callback_(this, &Transaction::OnIOComplete)), 125 ALLOW_THIS_IN_INITIALIZER_LIST( 126 cache_callback_(new CancelableCompletionCallback<Transaction>( 127 this, &Transaction::OnIOComplete))), 128 ALLOW_THIS_IN_INITIALIZER_LIST( 129 write_headers_callback_(new CancelableCompletionCallback<Transaction>( 130 this, &Transaction::OnIOComplete))) { 131 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == 132 arraysize(kValidationHeaders), 133 Invalid_number_of_validation_headers); 134 } 135 136 HttpCache::Transaction::~Transaction() { 137 // We may have to issue another IO, but we should never invoke the callback_ 138 // after this point. 139 callback_ = NULL; 140 141 if (cache_) { 142 if (entry_) { 143 bool cancel_request = reading_; 144 if (cancel_request) { 145 if (partial_.get()) { 146 entry_->disk_entry->CancelSparseIO(); 147 } else { 148 cancel_request &= (response_.headers->response_code() == 200); 149 } 150 } 151 152 cache_->DoneWithEntry(entry_, this, cancel_request); 153 } else if (cache_pending_) { 154 cache_->RemovePendingTransaction(this); 155 } 156 } 157 158 // If there is an outstanding callback, mark it as cancelled so running it 159 // does nothing. 160 cache_callback_->Cancel(); 161 write_headers_callback_->Cancel(); 162 163 // We could still have a cache read or write in progress, so we just null the 164 // cache_ pointer to signal that we are dead. See DoCacheReadCompleted. 165 cache_.reset(); 166 } 167 168 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 169 CompletionCallback* callback) { 170 DCHECK(buf); 171 DCHECK_GT(buf_len, 0); 172 DCHECK(callback); 173 if (!cache_ || !entry_) 174 return ERR_UNEXPECTED; 175 176 // We don't need to track this operation for anything. 177 // It could be possible to check if there is something already written and 178 // avoid writing again (it should be the same, right?), but let's allow the 179 // caller to "update" the contents with something new. 180 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 181 callback, true); 182 } 183 184 bool HttpCache::Transaction::AddTruncatedFlag() { 185 DCHECK(mode_ & WRITE); 186 187 // Don't set the flag for sparse entries. 188 if (partial_.get() && !truncated_) 189 return true; 190 191 if (!CanResume(true)) 192 return false; 193 194 truncated_ = true; 195 target_state_ = STATE_NONE; 196 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; 197 DoLoop(OK); 198 return true; 199 } 200 201 LoadState HttpCache::Transaction::GetWriterLoadState() const { 202 if (network_trans_.get()) 203 return network_trans_->GetLoadState(); 204 if (entry_ || !request_) 205 return LOAD_STATE_IDLE; 206 return LOAD_STATE_WAITING_FOR_CACHE; 207 } 208 209 const BoundNetLog& HttpCache::Transaction::net_log() const { 210 return net_log_; 211 } 212 213 int HttpCache::Transaction::Start(const HttpRequestInfo* request, 214 CompletionCallback* callback, 215 const BoundNetLog& net_log) { 216 DCHECK(request); 217 DCHECK(callback); 218 219 // Ensure that we only have one asynchronous call at a time. 220 DCHECK(!callback_); 221 DCHECK(!reading_); 222 DCHECK(!network_trans_.get()); 223 DCHECK(!entry_); 224 225 if (!cache_) 226 return ERR_UNEXPECTED; 227 228 SetRequest(net_log, request); 229 230 // We have to wait until the backend is initialized so we start the SM. 231 next_state_ = STATE_GET_BACKEND; 232 int rv = DoLoop(OK); 233 234 // Setting this here allows us to check for the existence of a callback_ to 235 // determine if we are still inside Start. 236 if (rv == ERR_IO_PENDING) 237 callback_ = callback; 238 239 return rv; 240 } 241 242 int HttpCache::Transaction::RestartIgnoringLastError( 243 CompletionCallback* callback) { 244 DCHECK(callback); 245 246 // Ensure that we only have one asynchronous call at a time. 247 DCHECK(!callback_); 248 249 if (!cache_) 250 return ERR_UNEXPECTED; 251 252 int rv = RestartNetworkRequest(); 253 254 if (rv == ERR_IO_PENDING) 255 callback_ = callback; 256 257 return rv; 258 } 259 260 int HttpCache::Transaction::RestartWithCertificate( 261 X509Certificate* client_cert, 262 CompletionCallback* callback) { 263 DCHECK(callback); 264 265 // Ensure that we only have one asynchronous call at a time. 266 DCHECK(!callback_); 267 268 if (!cache_) 269 return ERR_UNEXPECTED; 270 271 int rv = RestartNetworkRequestWithCertificate(client_cert); 272 273 if (rv == ERR_IO_PENDING) 274 callback_ = callback; 275 276 return rv; 277 } 278 279 int HttpCache::Transaction::RestartWithAuth( 280 const string16& username, 281 const string16& password, 282 CompletionCallback* callback) { 283 DCHECK(auth_response_.headers); 284 DCHECK(callback); 285 286 // Ensure that we only have one asynchronous call at a time. 287 DCHECK(!callback_); 288 289 if (!cache_) 290 return ERR_UNEXPECTED; 291 292 // Clear the intermediate response since we are going to start over. 293 auth_response_ = HttpResponseInfo(); 294 295 int rv = RestartNetworkRequestWithAuth(username, password); 296 297 if (rv == ERR_IO_PENDING) 298 callback_ = callback; 299 300 return rv; 301 } 302 303 bool HttpCache::Transaction::IsReadyToRestartForAuth() { 304 if (!network_trans_.get()) 305 return false; 306 return network_trans_->IsReadyToRestartForAuth(); 307 } 308 309 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 310 CompletionCallback* callback) { 311 DCHECK(buf); 312 DCHECK_GT(buf_len, 0); 313 DCHECK(callback); 314 315 DCHECK(!callback_); 316 317 if (!cache_) 318 return ERR_UNEXPECTED; 319 320 // If we have an intermediate auth response at this point, then it means the 321 // user wishes to read the network response (the error page). If there is a 322 // previous response in the cache then we should leave it intact. 323 if (auth_response_.headers && mode_ != NONE) { 324 DCHECK(mode_ & WRITE); 325 DoneWritingToEntry(mode_ == READ_WRITE); 326 mode_ = NONE; 327 } 328 329 reading_ = true; 330 int rv; 331 332 switch (mode_) { 333 case READ_WRITE: 334 DCHECK(partial_.get()); 335 if (!network_trans_.get()) { 336 // We are just reading from the cache, but we may be writing later. 337 rv = ReadFromEntry(buf, buf_len); 338 break; 339 } 340 case NONE: 341 case WRITE: 342 DCHECK(network_trans_.get()); 343 rv = ReadFromNetwork(buf, buf_len); 344 break; 345 case READ: 346 rv = ReadFromEntry(buf, buf_len); 347 break; 348 default: 349 NOTREACHED(); 350 rv = ERR_FAILED; 351 } 352 353 if (rv == ERR_IO_PENDING) { 354 DCHECK(!callback_); 355 callback_ = callback; 356 } 357 return rv; 358 } 359 360 void HttpCache::Transaction::StopCaching() { 361 } 362 363 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const { 364 // Null headers means we encountered an error or haven't a response yet 365 if (auth_response_.headers) 366 return &auth_response_; 367 return (response_.headers || response_.ssl_info.cert || 368 response_.cert_request_info) ? &response_ : NULL; 369 } 370 371 LoadState HttpCache::Transaction::GetLoadState() const { 372 LoadState state = GetWriterLoadState(); 373 if (state != LOAD_STATE_WAITING_FOR_CACHE) 374 return state; 375 376 if (cache_) 377 return cache_->GetLoadStateForPendingTransaction(this); 378 379 return LOAD_STATE_IDLE; 380 } 381 382 uint64 HttpCache::Transaction::GetUploadProgress() const { 383 if (network_trans_.get()) 384 return network_trans_->GetUploadProgress(); 385 return final_upload_progress_; 386 } 387 388 //----------------------------------------------------------------------------- 389 390 void HttpCache::Transaction::DoCallback(int rv) { 391 DCHECK(rv != ERR_IO_PENDING); 392 DCHECK(callback_); 393 394 // Since Run may result in Read being called, clear callback_ up front. 395 CompletionCallback* c = callback_; 396 callback_ = NULL; 397 c->Run(rv); 398 } 399 400 int HttpCache::Transaction::HandleResult(int rv) { 401 DCHECK(rv != ERR_IO_PENDING); 402 if (callback_) 403 DoCallback(rv); 404 return rv; 405 } 406 407 int HttpCache::Transaction::DoLoop(int result) { 408 DCHECK(next_state_ != STATE_NONE); 409 410 int rv = result; 411 do { 412 State state = next_state_; 413 next_state_ = STATE_NONE; 414 switch (state) { 415 case STATE_GET_BACKEND: 416 DCHECK_EQ(OK, rv); 417 rv = DoGetBackend(); 418 break; 419 case STATE_GET_BACKEND_COMPLETE: 420 rv = DoGetBackendComplete(rv); 421 break; 422 case STATE_SEND_REQUEST: 423 DCHECK_EQ(OK, rv); 424 rv = DoSendRequest(); 425 break; 426 case STATE_SEND_REQUEST_COMPLETE: 427 rv = DoSendRequestComplete(rv); 428 break; 429 case STATE_SUCCESSFUL_SEND_REQUEST: 430 DCHECK_EQ(OK, rv); 431 rv = DoSuccessfulSendRequest(); 432 break; 433 case STATE_NETWORK_READ: 434 DCHECK_EQ(OK, rv); 435 rv = DoNetworkRead(); 436 break; 437 case STATE_NETWORK_READ_COMPLETE: 438 rv = DoNetworkReadComplete(rv); 439 break; 440 case STATE_INIT_ENTRY: 441 DCHECK_EQ(OK, rv); 442 rv = DoInitEntry(); 443 break; 444 case STATE_OPEN_ENTRY: 445 DCHECK_EQ(OK, rv); 446 rv = DoOpenEntry(); 447 break; 448 case STATE_OPEN_ENTRY_COMPLETE: 449 rv = DoOpenEntryComplete(rv); 450 break; 451 case STATE_CREATE_ENTRY: 452 DCHECK_EQ(OK, rv); 453 rv = DoCreateEntry(); 454 break; 455 case STATE_CREATE_ENTRY_COMPLETE: 456 rv = DoCreateEntryComplete(rv); 457 break; 458 case STATE_DOOM_ENTRY: 459 DCHECK_EQ(OK, rv); 460 rv = DoDoomEntry(); 461 break; 462 case STATE_DOOM_ENTRY_COMPLETE: 463 rv = DoDoomEntryComplete(rv); 464 break; 465 case STATE_ADD_TO_ENTRY: 466 DCHECK_EQ(OK, rv); 467 rv = DoAddToEntry(); 468 break; 469 case STATE_ADD_TO_ENTRY_COMPLETE: 470 rv = DoAddToEntryComplete(rv); 471 break; 472 case STATE_NOTIFY_BEFORE_SEND_HEADERS: 473 DCHECK_EQ(OK, rv); 474 rv = DoNotifyBeforeSendHeaders(); 475 break; 476 case STATE_NOTIFY_BEFORE_SEND_HEADERS_COMPLETE: 477 rv = DoNotifyBeforeSendHeadersComplete(rv); 478 break; 479 case STATE_START_PARTIAL_CACHE_VALIDATION: 480 DCHECK_EQ(OK, rv); 481 rv = DoStartPartialCacheValidation(); 482 break; 483 case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION: 484 rv = DoCompletePartialCacheValidation(rv); 485 break; 486 case STATE_UPDATE_CACHED_RESPONSE: 487 DCHECK_EQ(OK, rv); 488 rv = DoUpdateCachedResponse(); 489 break; 490 case STATE_UPDATE_CACHED_RESPONSE_COMPLETE: 491 rv = DoUpdateCachedResponseComplete(rv); 492 break; 493 case STATE_OVERWRITE_CACHED_RESPONSE: 494 DCHECK_EQ(OK, rv); 495 rv = DoOverwriteCachedResponse(); 496 break; 497 case STATE_TRUNCATE_CACHED_DATA: 498 DCHECK_EQ(OK, rv); 499 rv = DoTruncateCachedData(); 500 break; 501 case STATE_TRUNCATE_CACHED_DATA_COMPLETE: 502 rv = DoTruncateCachedDataComplete(rv); 503 break; 504 case STATE_TRUNCATE_CACHED_METADATA: 505 DCHECK_EQ(OK, rv); 506 rv = DoTruncateCachedMetadata(); 507 break; 508 case STATE_TRUNCATE_CACHED_METADATA_COMPLETE: 509 rv = DoTruncateCachedMetadataComplete(rv); 510 break; 511 case STATE_PARTIAL_HEADERS_RECEIVED: 512 DCHECK_EQ(OK, rv); 513 rv = DoPartialHeadersReceived(); 514 break; 515 case STATE_CACHE_READ_RESPONSE: 516 DCHECK_EQ(OK, rv); 517 rv = DoCacheReadResponse(); 518 break; 519 case STATE_CACHE_READ_RESPONSE_COMPLETE: 520 rv = DoCacheReadResponseComplete(rv); 521 break; 522 case STATE_CACHE_WRITE_RESPONSE: 523 DCHECK_EQ(OK, rv); 524 rv = DoCacheWriteResponse(); 525 break; 526 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: 527 DCHECK_EQ(OK, rv); 528 rv = DoCacheWriteTruncatedResponse(); 529 break; 530 case STATE_CACHE_WRITE_RESPONSE_COMPLETE: 531 rv = DoCacheWriteResponseComplete(rv); 532 break; 533 case STATE_CACHE_READ_METADATA: 534 DCHECK_EQ(OK, rv); 535 rv = DoCacheReadMetadata(); 536 break; 537 case STATE_CACHE_READ_METADATA_COMPLETE: 538 rv = DoCacheReadMetadataComplete(rv); 539 break; 540 case STATE_CACHE_QUERY_DATA: 541 DCHECK_EQ(OK, rv); 542 rv = DoCacheQueryData(); 543 break; 544 case STATE_CACHE_QUERY_DATA_COMPLETE: 545 rv = DoCacheQueryDataComplete(rv); 546 break; 547 case STATE_CACHE_READ_DATA: 548 DCHECK_EQ(OK, rv); 549 rv = DoCacheReadData(); 550 break; 551 case STATE_CACHE_READ_DATA_COMPLETE: 552 rv = DoCacheReadDataComplete(rv); 553 break; 554 case STATE_CACHE_WRITE_DATA: 555 rv = DoCacheWriteData(rv); 556 break; 557 case STATE_CACHE_WRITE_DATA_COMPLETE: 558 rv = DoCacheWriteDataComplete(rv); 559 break; 560 default: 561 NOTREACHED() << "bad state"; 562 rv = ERR_FAILED; 563 break; 564 } 565 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 566 567 if (rv != ERR_IO_PENDING) 568 HandleResult(rv); 569 570 return rv; 571 } 572 573 int HttpCache::Transaction::DoGetBackend() { 574 cache_pending_ = true; 575 next_state_ = STATE_GET_BACKEND_COMPLETE; 576 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND, NULL); 577 return cache_->GetBackendForTransaction(this); 578 } 579 580 int HttpCache::Transaction::DoGetBackendComplete(int result) { 581 DCHECK(result == OK || result == ERR_FAILED); 582 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND, 583 result); 584 cache_pending_ = false; 585 586 if (!ShouldPassThrough()) { 587 cache_key_ = cache_->GenerateCacheKey(request_); 588 589 // Requested cache access mode. 590 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { 591 mode_ = READ; 592 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { 593 mode_ = WRITE; 594 } else { 595 mode_ = READ_WRITE; 596 } 597 598 // Downgrade to UPDATE if the request has been externally conditionalized. 599 if (external_validation_.initialized) { 600 if (mode_ & WRITE) { 601 // Strip off the READ_DATA bit (and maybe add back a READ_META bit 602 // in case READ was off). 603 mode_ = UPDATE; 604 } else { 605 mode_ = NONE; 606 } 607 } 608 } 609 610 // If must use cache, then we must fail. This can happen for back/forward 611 // navigations to a page generated via a form post. 612 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) 613 return ERR_CACHE_MISS; 614 615 if (mode_ == NONE) { 616 if (partial_.get()) 617 partial_->RestoreHeaders(&custom_request_->extra_headers); 618 next_state_ = STATE_SEND_REQUEST; 619 } else { 620 next_state_ = STATE_INIT_ENTRY; 621 } 622 623 return OK; 624 } 625 626 int HttpCache::Transaction::DoSendRequest() { 627 DCHECK(mode_ & WRITE || mode_ == NONE); 628 DCHECK(!network_trans_.get()); 629 630 // Create a network transaction. 631 int rv = cache_->network_layer_->CreateTransaction(&network_trans_); 632 if (rv != OK) 633 return rv; 634 635 next_state_ = STATE_SEND_REQUEST_COMPLETE; 636 rv = network_trans_->Start(request_, &io_callback_, net_log_); 637 return rv; 638 } 639 640 int HttpCache::Transaction::DoSendRequestComplete(int result) { 641 if (!cache_) 642 return ERR_UNEXPECTED; 643 644 if (result == OK) { 645 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 646 return OK; 647 } 648 649 if (IsCertificateError(result)) { 650 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 651 // If we get a certificate error, then there is a certificate in ssl_info, 652 // so GetResponseInfo() should never returns NULL here. 653 DCHECK(response); 654 response_.ssl_info = response->ssl_info; 655 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 656 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 657 DCHECK(response); 658 response_.cert_request_info = response->cert_request_info; 659 } 660 return result; 661 } 662 663 // We received the response headers and there is no error. 664 int HttpCache::Transaction::DoSuccessfulSendRequest() { 665 DCHECK(!new_response_); 666 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); 667 if (new_response->headers->response_code() == 401 || 668 new_response->headers->response_code() == 407) { 669 auth_response_ = *new_response; 670 return OK; 671 } 672 673 new_response_ = new_response; 674 if (!ValidatePartialResponse(&server_responded_206_) && 675 !auth_response_.headers) { 676 // Something went wrong with this request and we have to restart it. 677 // If we have an authentication response, we are exposed to weird things 678 // hapenning if the user cancels the authentication before we receive 679 // the new response. 680 response_ = HttpResponseInfo(); 681 network_trans_.reset(); 682 new_response_ = NULL; 683 next_state_ = STATE_SEND_REQUEST; 684 return OK; 685 } 686 if (server_responded_206_ && mode_ == READ_WRITE && !truncated_ && 687 !is_sparse_) { 688 // We have stored the full entry, but it changed and the server is 689 // sending a range. We have to delete the old entry. 690 DoneWritingToEntry(false); 691 } 692 693 if (new_response_->headers->response_code() == 416) { 694 DCHECK_EQ(NONE, mode_); 695 response_ = *new_response_; 696 return OK; 697 } 698 699 // Are we expecting a response to a conditional query? 700 if (mode_ == READ_WRITE || mode_ == UPDATE) { 701 if (new_response->headers->response_code() == 304 || 702 server_responded_206_) { 703 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 704 return OK; 705 } 706 mode_ = WRITE; 707 } 708 709 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 710 return OK; 711 } 712 713 int HttpCache::Transaction::DoNetworkRead() { 714 next_state_ = STATE_NETWORK_READ_COMPLETE; 715 return network_trans_->Read(read_buf_, io_buf_len_, &io_callback_); 716 } 717 718 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 719 DCHECK(mode_ & WRITE || mode_ == NONE); 720 721 if (!cache_) 722 return ERR_UNEXPECTED; 723 724 // If there is an error and we are saving the data, just tell the user about 725 // it and wait until the destructor runs to see if we can keep the data. 726 if (mode_ != NONE && result < 0) 727 return result; 728 729 next_state_ = STATE_CACHE_WRITE_DATA; 730 return result; 731 } 732 733 int HttpCache::Transaction::DoInitEntry() { 734 DCHECK(!new_entry_); 735 736 if (!cache_) 737 return ERR_UNEXPECTED; 738 739 if (mode_ == WRITE) { 740 next_state_ = STATE_DOOM_ENTRY; 741 return OK; 742 } 743 744 next_state_ = STATE_OPEN_ENTRY; 745 return OK; 746 } 747 748 int HttpCache::Transaction::DoOpenEntry() { 749 DCHECK(!new_entry_); 750 next_state_ = STATE_OPEN_ENTRY_COMPLETE; 751 cache_pending_ = true; 752 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, NULL); 753 return cache_->OpenEntry(cache_key_, &new_entry_, this); 754 } 755 756 int HttpCache::Transaction::DoOpenEntryComplete(int result) { 757 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 758 // OK, otherwise the cache will end up with an active entry without any 759 // transaction attached. 760 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); 761 cache_pending_ = false; 762 if (result == OK) { 763 next_state_ = STATE_ADD_TO_ENTRY; 764 return OK; 765 } 766 767 if (result == ERR_CACHE_RACE) { 768 next_state_ = STATE_INIT_ENTRY; 769 return OK; 770 } 771 772 if (mode_ == READ_WRITE) { 773 mode_ = WRITE; 774 next_state_ = STATE_CREATE_ENTRY; 775 return OK; 776 } 777 if (mode_ == UPDATE) { 778 // There is no cache entry to update; proceed without caching. 779 mode_ = NONE; 780 next_state_ = STATE_SEND_REQUEST; 781 return OK; 782 } 783 if (cache_->mode() == PLAYBACK) 784 DVLOG(1) << "Playback Cache Miss: " << request_->url; 785 786 // The entry does not exist, and we are not permitted to create a new entry, 787 // so we must fail. 788 return ERR_CACHE_MISS; 789 } 790 791 int HttpCache::Transaction::DoCreateEntry() { 792 DCHECK(!new_entry_); 793 next_state_ = STATE_CREATE_ENTRY_COMPLETE; 794 cache_pending_ = true; 795 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, NULL); 796 return cache_->CreateEntry(cache_key_, &new_entry_, this); 797 } 798 799 int HttpCache::Transaction::DoCreateEntryComplete(int result) { 800 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 801 // OK, otherwise the cache will end up with an active entry without any 802 // transaction attached. 803 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, 804 result); 805 cache_pending_ = false; 806 next_state_ = STATE_ADD_TO_ENTRY; 807 808 if (result == ERR_CACHE_RACE) { 809 next_state_ = STATE_INIT_ENTRY; 810 return OK; 811 } 812 813 if (result != OK) { 814 // We have a race here: Maybe we failed to open the entry and decided to 815 // create one, but by the time we called create, another transaction already 816 // created the entry. If we want to eliminate this issue, we need an atomic 817 // OpenOrCreate() method exposed by the disk cache. 818 DLOG(WARNING) << "Unable to create cache entry"; 819 mode_ = NONE; 820 if (partial_.get()) 821 partial_->RestoreHeaders(&custom_request_->extra_headers); 822 next_state_ = STATE_SEND_REQUEST; 823 } 824 return OK; 825 } 826 827 int HttpCache::Transaction::DoDoomEntry() { 828 next_state_ = STATE_DOOM_ENTRY_COMPLETE; 829 cache_pending_ = true; 830 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, NULL); 831 return cache_->DoomEntry(cache_key_, this); 832 } 833 834 int HttpCache::Transaction::DoDoomEntryComplete(int result) { 835 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); 836 next_state_ = STATE_CREATE_ENTRY; 837 cache_pending_ = false; 838 if (result == ERR_CACHE_RACE) 839 next_state_ = STATE_INIT_ENTRY; 840 841 return OK; 842 } 843 844 int HttpCache::Transaction::DoAddToEntry() { 845 DCHECK(new_entry_); 846 cache_pending_ = true; 847 next_state_ = STATE_ADD_TO_ENTRY_COMPLETE; 848 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY, NULL); 849 DCHECK(entry_lock_waiting_since_.is_null()); 850 entry_lock_waiting_since_ = base::TimeTicks::Now(); 851 return cache_->AddTransactionToEntry(new_entry_, this); 852 } 853 854 int HttpCache::Transaction::DoAddToEntryComplete(int result) { 855 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY, 856 result); 857 858 const base::TimeDelta entry_lock_wait = 859 base::TimeTicks::Now() - entry_lock_waiting_since_; 860 UMA_HISTOGRAM_TIMES("HttpCache.EntryLockWait", entry_lock_wait); 861 static const bool prefetching_fieldtrial = 862 base::FieldTrialList::Find("Prefetch") && 863 !base::FieldTrialList::Find("Prefetch")->group_name().empty(); 864 if (prefetching_fieldtrial) { 865 UMA_HISTOGRAM_TIMES( 866 base::FieldTrial::MakeName("HttpCache.EntryLockWait", "Prefetch"), 867 entry_lock_wait); 868 } 869 870 entry_lock_waiting_since_ = base::TimeTicks(); 871 DCHECK(new_entry_); 872 cache_pending_ = false; 873 874 if (result == ERR_CACHE_RACE) { 875 new_entry_ = NULL; 876 next_state_ = STATE_INIT_ENTRY; 877 return OK; 878 } 879 880 if (result != OK) { 881 // If there is a failure, the cache should have taken care of new_entry_. 882 NOTREACHED(); 883 new_entry_ = NULL; 884 return result; 885 } 886 887 entry_ = new_entry_; 888 new_entry_ = NULL; 889 890 if (mode_ == WRITE) { 891 if (partial_.get()) 892 partial_->RestoreHeaders(&custom_request_->extra_headers); 893 next_state_ = STATE_SEND_REQUEST; 894 } else { 895 // We have to read the headers from the cached entry. 896 DCHECK(mode_ & READ_META); 897 next_state_ = STATE_CACHE_READ_RESPONSE; 898 } 899 return OK; 900 } 901 902 int HttpCache::Transaction::DoNotifyBeforeSendHeaders() { 903 // Balanced in DoNotifyBeforeSendHeadersComplete. 904 cache_callback_->AddRef(); 905 next_state_ = STATE_NOTIFY_BEFORE_SEND_HEADERS_COMPLETE; 906 907 if (cache_->GetSession() && cache_->GetSession()->network_delegate()) { 908 // TODO(mpcomplete): need to be able to modify these headers. 909 HttpRequestHeaders headers = request_->extra_headers; 910 return cache_->GetSession()->network_delegate()->NotifyBeforeSendHeaders( 911 request_->request_id, cache_callback_, &headers); 912 } 913 914 return OK; 915 } 916 917 int HttpCache::Transaction::DoNotifyBeforeSendHeadersComplete(int result) { 918 cache_callback_->Release(); // Balanced in DoNotifyBeforeSendHeaders. 919 920 // We now have access to the cache entry. 921 // 922 // o if we are a reader for the transaction, then we can start reading the 923 // cache entry. 924 // 925 // o if we can read or write, then we should check if the cache entry needs 926 // to be validated and then issue a network request if needed or just read 927 // from the cache if the cache entry is already valid. 928 // 929 // o if we are set to UPDATE, then we are handling an externally 930 // conditionalized request (if-modified-since / if-none-match). We check 931 // if the request headers define a validation request. 932 // 933 if (result == net::OK) { 934 switch (mode_) { 935 case READ: 936 result = BeginCacheRead(); 937 break; 938 case READ_WRITE: 939 result = BeginPartialCacheValidation(); 940 break; 941 case UPDATE: 942 result = BeginExternallyConditionalizedRequest(); 943 break; 944 case WRITE: 945 default: 946 NOTREACHED(); 947 result = ERR_FAILED; 948 } 949 } 950 return result; 951 } 952 953 // We may end up here multiple times for a given request. 954 int HttpCache::Transaction::DoStartPartialCacheValidation() { 955 if (mode_ == NONE) 956 return OK; 957 958 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION; 959 return partial_->ShouldValidateCache(entry_->disk_entry, &io_callback_); 960 } 961 962 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { 963 if (!result) { 964 // This is the end of the request. 965 if (mode_ & WRITE) { 966 DoneWritingToEntry(true); 967 } else { 968 cache_->DoneReadingFromEntry(entry_, this); 969 entry_ = NULL; 970 } 971 return result; 972 } 973 974 if (result < 0) 975 return result; 976 977 partial_->PrepareCacheValidation(entry_->disk_entry, 978 &custom_request_->extra_headers); 979 980 if (reading_ && partial_->IsCurrentRangeCached()) { 981 next_state_ = STATE_CACHE_READ_DATA; 982 return OK; 983 } 984 985 return BeginCacheValidation(); 986 } 987 988 // We received 304 or 206 and we want to update the cached response headers. 989 int HttpCache::Transaction::DoUpdateCachedResponse() { 990 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 991 int rv = OK; 992 // Update cached response based on headers in new_response. 993 // TODO(wtc): should we update cached certificate (response_.ssl_info), too? 994 response_.headers->Update(*new_response_->headers); 995 response_.response_time = new_response_->response_time; 996 response_.request_time = new_response_->request_time; 997 998 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { 999 int ret = cache_->DoomEntry(cache_key_, NULL); 1000 DCHECK_EQ(OK, ret); 1001 } else { 1002 // If we are already reading, we already updated the headers for this 1003 // request; doing it again will change Content-Length. 1004 if (!reading_) { 1005 target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1006 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1007 rv = OK; 1008 } 1009 } 1010 return rv; 1011 } 1012 1013 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { 1014 if (mode_ == UPDATE) { 1015 DCHECK(!server_responded_206_); 1016 // We got a "not modified" response and already updated the corresponding 1017 // cache entry above. 1018 // 1019 // By closing the cached entry now, we make sure that the 304 rather than 1020 // the cached 200 response, is what will be returned to the user. 1021 DoneWritingToEntry(true); 1022 } else if (entry_ && !server_responded_206_) { 1023 DCHECK_EQ(READ_WRITE, mode_); 1024 if (!partial_.get() || partial_->IsLastRange()) { 1025 cache_->ConvertWriterToReader(entry_); 1026 mode_ = READ; 1027 } 1028 // We no longer need the network transaction, so destroy it. 1029 final_upload_progress_ = network_trans_->GetUploadProgress(); 1030 network_trans_.reset(); 1031 } else if (entry_ && server_responded_206_ && truncated_ && 1032 partial_->initial_validation()) { 1033 // We just finished the validation of a truncated entry, and the server 1034 // is willing to resume the operation. Now we go back and start serving 1035 // the first part to the user. 1036 network_trans_.reset(); 1037 new_response_ = NULL; 1038 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1039 partial_->SetRangeToStartDownload(); 1040 return OK; 1041 } 1042 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 1043 return OK; 1044 } 1045 1046 int HttpCache::Transaction::DoOverwriteCachedResponse() { 1047 if (mode_ & READ) { 1048 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1049 return OK; 1050 } 1051 1052 // We change the value of Content-Length for partial content. 1053 if (server_responded_206_ && partial_.get()) 1054 partial_->FixContentLength(new_response_->headers); 1055 1056 response_ = *new_response_; 1057 1058 if (server_responded_206_ && !CanResume(false)) { 1059 // There is no point in storing this resource because it will never be used. 1060 DoneWritingToEntry(false); 1061 if (partial_.get()) 1062 partial_->FixResponseHeaders(response_.headers, true); 1063 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1064 return OK; 1065 } 1066 1067 target_state_ = STATE_TRUNCATE_CACHED_DATA; 1068 next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE : 1069 STATE_CACHE_WRITE_RESPONSE; 1070 return OK; 1071 } 1072 1073 int HttpCache::Transaction::DoTruncateCachedData() { 1074 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1075 cache_callback_->AddRef(); // Balanced in DoTruncateCachedDataComplete. 1076 if (!entry_) 1077 return OK; 1078 if (net_log_.IsLoggingAllEvents()) 1079 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, NULL); 1080 1081 // Truncate the stream. 1082 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, cache_callback_); 1083 } 1084 1085 int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) { 1086 if (net_log_.IsLoggingAllEvents() && entry_) { 1087 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1088 result); 1089 } 1090 1091 // Balance the AddRef from DoTruncateCachedData. 1092 cache_callback_->Release(); 1093 next_state_ = STATE_TRUNCATE_CACHED_METADATA; 1094 return OK; 1095 } 1096 1097 int HttpCache::Transaction::DoTruncateCachedMetadata() { 1098 next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE; 1099 cache_callback_->AddRef(); // Balanced in DoTruncateCachedMetadataComplete. 1100 if (!entry_) 1101 return OK; 1102 1103 if (net_log_.IsLoggingAllEvents()) 1104 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL); 1105 return WriteToEntry(kMetadataIndex, 0, NULL, 0, cache_callback_); 1106 } 1107 1108 int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) { 1109 if (net_log_.IsLoggingAllEvents() && entry_) { 1110 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 1111 result); 1112 } 1113 1114 // Balance the AddRef from DoTruncateCachedMetadata. 1115 cache_callback_->Release(); 1116 1117 // If this response is a redirect, then we can stop writing now. (We don't 1118 // need to cache the response body of a redirect.) 1119 if (response_.headers->IsRedirect(NULL)) 1120 DoneWritingToEntry(true); 1121 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1122 return OK; 1123 } 1124 1125 int HttpCache::Transaction::DoPartialHeadersReceived() { 1126 new_response_ = NULL; 1127 if (entry_ && !partial_.get() && 1128 entry_->disk_entry->GetDataSize(kMetadataIndex)) 1129 next_state_ = STATE_CACHE_READ_METADATA; 1130 1131 if (!partial_.get()) 1132 return OK; 1133 1134 if (reading_) { 1135 if (network_trans_.get()) { 1136 next_state_ = STATE_NETWORK_READ; 1137 } else { 1138 next_state_ = STATE_CACHE_READ_DATA; 1139 } 1140 } else if (mode_ != NONE) { 1141 // We are about to return the headers for a byte-range request to the user, 1142 // so let's fix them. 1143 partial_->FixResponseHeaders(response_.headers, true); 1144 } 1145 return OK; 1146 } 1147 1148 int HttpCache::Transaction::DoCacheReadResponse() { 1149 DCHECK(entry_); 1150 next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE; 1151 1152 io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex); 1153 read_buf_ = new IOBuffer(io_buf_len_); 1154 1155 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO, NULL); 1156 cache_callback_->AddRef(); // Balanced in DoCacheReadResponseComplete. 1157 return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_, 1158 io_buf_len_, cache_callback_); 1159 } 1160 1161 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { 1162 cache_callback_->Release(); // Balance the AddRef from DoCacheReadResponse. 1163 1164 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1165 if (result != io_buf_len_ || 1166 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, 1167 &response_, &truncated_)) { 1168 DLOG(ERROR) << "ReadData failed: " << result; 1169 return ERR_CACHE_READ_FAILURE; 1170 } 1171 1172 next_state_ = STATE_NOTIFY_BEFORE_SEND_HEADERS; 1173 return OK; 1174 } 1175 1176 int HttpCache::Transaction::DoCacheWriteResponse() { 1177 if (net_log_.IsLoggingAllEvents() && entry_) 1178 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL); 1179 return WriteResponseInfoToEntry(false); 1180 } 1181 1182 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 1183 if (net_log_.IsLoggingAllEvents() && entry_) 1184 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL); 1185 return WriteResponseInfoToEntry(true); 1186 } 1187 1188 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1189 next_state_ = target_state_; 1190 target_state_ = STATE_NONE; 1191 if (!entry_) 1192 return OK; 1193 if (net_log_.IsLoggingAllEvents()) { 1194 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 1195 result); 1196 } 1197 1198 // Balance the AddRef from WriteResponseInfoToEntry. 1199 write_headers_callback_->Release(); 1200 if (result != io_buf_len_) { 1201 DLOG(ERROR) << "failed to write response info to cache"; 1202 DoneWritingToEntry(false); 1203 } 1204 return OK; 1205 } 1206 1207 int HttpCache::Transaction::DoCacheReadMetadata() { 1208 DCHECK(entry_); 1209 DCHECK(!response_.metadata); 1210 next_state_ = STATE_CACHE_READ_METADATA_COMPLETE; 1211 1212 response_.metadata = 1213 new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex)); 1214 1215 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO, NULL); 1216 cache_callback_->AddRef(); // Balanced in DoCacheReadMetadataComplete. 1217 return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata, 1218 response_.metadata->size(), 1219 cache_callback_); 1220 } 1221 1222 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1223 cache_callback_->Release(); // Balance the AddRef from DoCacheReadMetadata. 1224 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1225 if (result != response_.metadata->size()) { 1226 DLOG(ERROR) << "ReadData failed: " << result; 1227 return ERR_CACHE_READ_FAILURE; 1228 } 1229 1230 return OK; 1231 } 1232 1233 int HttpCache::Transaction::DoCacheQueryData() { 1234 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; 1235 1236 // Balanced in ValidateEntryHeadersAndContinue. 1237 cache_callback_->AddRef(); 1238 return entry_->disk_entry->ReadyForSparseIO(cache_callback_); 1239 } 1240 1241 int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { 1242 DCHECK_EQ(OK, result); 1243 // Balance the AddRef from BeginPartialCacheValidation. 1244 cache_callback_->Release(); 1245 if (!cache_) 1246 return ERR_UNEXPECTED; 1247 1248 return ValidateEntryHeadersAndContinue(true); 1249 } 1250 1251 int HttpCache::Transaction::DoCacheReadData() { 1252 DCHECK(entry_); 1253 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 1254 cache_callback_->AddRef(); // Balanced in DoCacheReadDataComplete. 1255 1256 if (net_log_.IsLoggingAllEvents()) 1257 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA, NULL); 1258 if (partial_.get()) { 1259 return partial_->CacheRead(entry_->disk_entry, read_buf_, io_buf_len_, 1260 cache_callback_); 1261 } 1262 1263 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, 1264 read_buf_, io_buf_len_, cache_callback_); 1265 } 1266 1267 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1268 cache_callback_->Release(); // Balance the AddRef from DoCacheReadData. 1269 if (net_log_.IsLoggingAllEvents()) { 1270 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1271 result); 1272 } 1273 1274 if (!cache_) 1275 return ERR_UNEXPECTED; 1276 1277 if (partial_.get()) 1278 return DoPartialCacheReadCompleted(result); 1279 1280 if (result > 0) { 1281 read_offset_ += result; 1282 } else if (result == 0) { // End of file. 1283 cache_->DoneReadingFromEntry(entry_, this); 1284 entry_ = NULL; 1285 } 1286 return result; 1287 } 1288 1289 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1290 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1291 write_len_ = num_bytes; 1292 if (net_log_.IsLoggingAllEvents() && entry_) 1293 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, NULL); 1294 cache_callback_->AddRef(); // Balanced in DoCacheWriteDataComplete. 1295 1296 return AppendResponseDataToEntry(read_buf_, num_bytes, cache_callback_); 1297 } 1298 1299 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 1300 if (net_log_.IsLoggingAllEvents() && entry_) { 1301 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1302 result); 1303 } 1304 // Balance the AddRef from DoCacheWriteData. 1305 cache_callback_->Release(); 1306 if (!cache_) 1307 return ERR_UNEXPECTED; 1308 1309 if (result != write_len_) { 1310 DLOG(ERROR) << "failed to write response data to cache"; 1311 DoneWritingToEntry(false); 1312 1313 // We want to ignore errors writing to disk and just keep reading from 1314 // the network. 1315 result = write_len_; 1316 } 1317 1318 if (partial_.get()) { 1319 // This may be the last request. 1320 if (!(result == 0 && !truncated_ && 1321 (partial_->IsLastRange() || mode_ == WRITE))) 1322 return DoPartialNetworkReadCompleted(result); 1323 } 1324 1325 if (result == 0) // End of file. 1326 DoneWritingToEntry(true); 1327 1328 return result; 1329 } 1330 1331 //----------------------------------------------------------------------------- 1332 1333 void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log, 1334 const HttpRequestInfo* request) { 1335 net_log_ = net_log; 1336 request_ = request; 1337 effective_load_flags_ = request_->load_flags; 1338 1339 switch (cache_->mode()) { 1340 case NORMAL: 1341 break; 1342 case RECORD: 1343 // When in record mode, we want to NEVER load from the cache. 1344 // The reason for this is beacuse we save the Set-Cookie headers 1345 // (intentionally). If we read from the cache, we replay them 1346 // prematurely. 1347 effective_load_flags_ |= LOAD_BYPASS_CACHE; 1348 break; 1349 case PLAYBACK: 1350 // When in playback mode, we want to load exclusively from the cache. 1351 effective_load_flags_ |= LOAD_ONLY_FROM_CACHE; 1352 break; 1353 case DISABLE: 1354 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1355 break; 1356 } 1357 1358 // Some headers imply load flags. The order here is significant. 1359 // 1360 // LOAD_DISABLE_CACHE : no cache read or write 1361 // LOAD_BYPASS_CACHE : no cache read 1362 // LOAD_VALIDATE_CACHE : no cache read unless validation 1363 // 1364 // The former modes trump latter modes, so if we find a matching header we 1365 // can stop iterating kSpecialHeaders. 1366 // 1367 static const struct { 1368 const HeaderNameAndValue* search; 1369 int load_flag; 1370 } kSpecialHeaders[] = { 1371 { kPassThroughHeaders, LOAD_DISABLE_CACHE }, 1372 { kForceFetchHeaders, LOAD_BYPASS_CACHE }, 1373 { kForceValidateHeaders, LOAD_VALIDATE_CACHE }, 1374 }; 1375 1376 bool range_found = false; 1377 bool external_validation_error = false; 1378 1379 if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange)) 1380 range_found = true; 1381 1382 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) { 1383 if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) { 1384 effective_load_flags_ |= kSpecialHeaders[i].load_flag; 1385 break; 1386 } 1387 } 1388 1389 // Check for conditionalization headers which may correspond with a 1390 // cache validation request. 1391 for (size_t i = 0; i < arraysize(kValidationHeaders); ++i) { 1392 const ValidationHeaderInfo& info = kValidationHeaders[i]; 1393 std::string validation_value; 1394 if (request_->extra_headers.GetHeader( 1395 info.request_header_name, &validation_value)) { 1396 if (!external_validation_.values[i].empty() || 1397 validation_value.empty()) 1398 external_validation_error = true; 1399 external_validation_.values[i] = validation_value; 1400 external_validation_.initialized = true; 1401 break; 1402 } 1403 } 1404 1405 // We don't support ranges and validation headers. 1406 if (range_found && external_validation_.initialized) { 1407 LOG(WARNING) << "Byte ranges AND validation headers found."; 1408 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1409 } 1410 1411 // If there is more than one validation header, we can't treat this request as 1412 // a cache validation, since we don't know for sure which header the server 1413 // will give us a response for (and they could be contradictory). 1414 if (external_validation_error) { 1415 LOG(WARNING) << "Multiple or malformed validation headers found."; 1416 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1417 } 1418 1419 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { 1420 partial_.reset(new PartialData); 1421 if (partial_->Init(request_->extra_headers)) { 1422 // We will be modifying the actual range requested to the server, so 1423 // let's remove the header here. 1424 custom_request_.reset(new HttpRequestInfo(*request_)); 1425 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange); 1426 request_ = custom_request_.get(); 1427 partial_->SetHeaders(custom_request_->extra_headers); 1428 } else { 1429 // The range is invalid or we cannot handle it properly. 1430 VLOG(1) << "Invalid byte range found."; 1431 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1432 partial_.reset(NULL); 1433 } 1434 } 1435 } 1436 1437 bool HttpCache::Transaction::ShouldPassThrough() { 1438 // We may have a null disk_cache if there is an error we cannot recover from, 1439 // like not enough disk space, or sharing violations. 1440 if (!cache_->disk_cache_.get()) 1441 return true; 1442 1443 // When using the record/playback modes, we always use the cache 1444 // and we never pass through. 1445 if (cache_->mode() == RECORD || cache_->mode() == PLAYBACK) 1446 return false; 1447 1448 if (effective_load_flags_ & LOAD_DISABLE_CACHE) 1449 return true; 1450 1451 if (request_->method == "GET") 1452 return false; 1453 1454 if (request_->method == "POST" && 1455 request_->upload_data && request_->upload_data->identifier()) 1456 return false; 1457 1458 // TODO(darin): add support for caching HEAD responses 1459 return true; 1460 } 1461 1462 int HttpCache::Transaction::BeginCacheRead() { 1463 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. 1464 if (response_.headers->response_code() == 206 || partial_.get()) { 1465 NOTREACHED(); 1466 return ERR_CACHE_MISS; 1467 } 1468 1469 // We don't have the whole resource. 1470 if (truncated_) 1471 return ERR_CACHE_MISS; 1472 1473 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) 1474 next_state_ = STATE_CACHE_READ_METADATA; 1475 1476 return OK; 1477 } 1478 1479 int HttpCache::Transaction::BeginCacheValidation() { 1480 DCHECK(mode_ == READ_WRITE); 1481 1482 bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE || 1483 !RequiresValidation(); 1484 1485 if (truncated_) 1486 skip_validation = !partial_->initial_validation(); 1487 1488 if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_) 1489 skip_validation = false; 1490 1491 if (skip_validation) { 1492 if (partial_.get()) { 1493 // We are going to return the saved response headers to the caller, so 1494 // we may need to adjust them first. 1495 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1496 return OK; 1497 } 1498 cache_->ConvertWriterToReader(entry_); 1499 mode_ = READ; 1500 1501 if (entry_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) 1502 next_state_ = STATE_CACHE_READ_METADATA; 1503 } else { 1504 // Make the network request conditional, to see if we may reuse our cached 1505 // response. If we cannot do so, then we just resort to a normal fetch. 1506 // Our mode remains READ_WRITE for a conditional request. We'll switch to 1507 // either READ or WRITE mode once we hear back from the server. 1508 if (!ConditionalizeRequest()) { 1509 DCHECK(!partial_.get()); 1510 DCHECK_NE(206, response_.headers->response_code()); 1511 mode_ = WRITE; 1512 } 1513 next_state_ = STATE_SEND_REQUEST; 1514 } 1515 return OK; 1516 } 1517 1518 int HttpCache::Transaction::BeginPartialCacheValidation() { 1519 DCHECK(mode_ == READ_WRITE); 1520 1521 if (response_.headers->response_code() != 206 && !partial_.get() && 1522 !truncated_) 1523 return BeginCacheValidation(); 1524 1525 bool byte_range_requested = partial_.get() != NULL; 1526 if (byte_range_requested) { 1527 next_state_ = STATE_CACHE_QUERY_DATA; 1528 return OK; 1529 } 1530 // The request is not for a range, but we have stored just ranges. 1531 partial_.reset(new PartialData()); 1532 partial_->SetHeaders(request_->extra_headers); 1533 if (!custom_request_.get()) { 1534 custom_request_.reset(new HttpRequestInfo(*request_)); 1535 request_ = custom_request_.get(); 1536 } 1537 1538 return ValidateEntryHeadersAndContinue(false); 1539 } 1540 1541 // This should only be called once per request. 1542 int HttpCache::Transaction::ValidateEntryHeadersAndContinue( 1543 bool byte_range_requested) { 1544 DCHECK(mode_ == READ_WRITE); 1545 1546 if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry, 1547 truncated_)) { 1548 // The stored data cannot be used. Get rid of it and restart this request. 1549 // We need to also reset the |truncated_| flag as a new entry is created. 1550 DoomPartialEntry(!byte_range_requested); 1551 mode_ = WRITE; 1552 truncated_ = false; 1553 next_state_ = STATE_INIT_ENTRY; 1554 return OK; 1555 } 1556 1557 if (response_.headers->response_code() == 206) 1558 is_sparse_ = true; 1559 1560 if (!partial_->IsRequestedRangeOK()) { 1561 // The stored data is fine, but the request may be invalid. 1562 invalid_range_ = true; 1563 } 1564 1565 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1566 return OK; 1567 } 1568 1569 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { 1570 DCHECK_EQ(UPDATE, mode_); 1571 DCHECK(external_validation_.initialized); 1572 1573 for (size_t i = 0; i < arraysize(kValidationHeaders); i++) { 1574 if (external_validation_.values[i].empty()) 1575 continue; 1576 // Retrieve either the cached response's "etag" or "last-modified" header. 1577 std::string validator; 1578 response_.headers->EnumerateHeader( 1579 NULL, 1580 kValidationHeaders[i].related_response_header_name, 1581 &validator); 1582 1583 if (response_.headers->response_code() != 200 || truncated_ || 1584 validator.empty() || validator != external_validation_.values[i]) { 1585 // The externally conditionalized request is not a validation request 1586 // for our existing cache entry. Proceed with caching disabled. 1587 DoneWritingToEntry(true); 1588 } 1589 } 1590 1591 next_state_ = STATE_SEND_REQUEST; 1592 return OK; 1593 } 1594 1595 int HttpCache::Transaction::RestartNetworkRequest() { 1596 DCHECK(mode_ & WRITE || mode_ == NONE); 1597 DCHECK(network_trans_.get()); 1598 DCHECK_EQ(STATE_NONE, next_state_); 1599 1600 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1601 int rv = network_trans_->RestartIgnoringLastError(&io_callback_); 1602 if (rv != ERR_IO_PENDING) 1603 return DoLoop(rv); 1604 return rv; 1605 } 1606 1607 int HttpCache::Transaction::RestartNetworkRequestWithCertificate( 1608 X509Certificate* client_cert) { 1609 DCHECK(mode_ & WRITE || mode_ == NONE); 1610 DCHECK(network_trans_.get()); 1611 DCHECK_EQ(STATE_NONE, next_state_); 1612 1613 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1614 int rv = network_trans_->RestartWithCertificate(client_cert, &io_callback_); 1615 if (rv != ERR_IO_PENDING) 1616 return DoLoop(rv); 1617 return rv; 1618 } 1619 1620 int HttpCache::Transaction::RestartNetworkRequestWithAuth( 1621 const string16& username, 1622 const string16& password) { 1623 DCHECK(mode_ & WRITE || mode_ == NONE); 1624 DCHECK(network_trans_.get()); 1625 DCHECK_EQ(STATE_NONE, next_state_); 1626 1627 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1628 int rv = network_trans_->RestartWithAuth(username, password, &io_callback_); 1629 if (rv != ERR_IO_PENDING) 1630 return DoLoop(rv); 1631 return rv; 1632 } 1633 1634 bool HttpCache::Transaction::RequiresValidation() { 1635 // TODO(darin): need to do more work here: 1636 // - make sure we have a matching request method 1637 // - watch out for cached responses that depend on authentication 1638 // In playback mode, nothing requires validation. 1639 if (cache_->mode() == net::HttpCache::PLAYBACK) 1640 return false; 1641 1642 if (effective_load_flags_ & LOAD_VALIDATE_CACHE) 1643 return true; 1644 1645 if (response_.headers->RequiresValidation( 1646 response_.request_time, response_.response_time, Time::Now())) 1647 return true; 1648 1649 // Since Vary header computation is fairly expensive, we save it for last. 1650 if (response_.vary_data.is_valid() && 1651 !response_.vary_data.MatchesRequest(*request_, *response_.headers)) 1652 return true; 1653 1654 return false; 1655 } 1656 1657 bool HttpCache::Transaction::ConditionalizeRequest() { 1658 DCHECK(response_.headers); 1659 1660 // This only makes sense for cached 200 or 206 responses. 1661 if (response_.headers->response_code() != 200 && 1662 response_.headers->response_code() != 206) 1663 return false; 1664 1665 // We should have handled this case before. 1666 DCHECK(response_.headers->response_code() != 206 || 1667 response_.headers->HasStrongValidators()); 1668 1669 // Just use the first available ETag and/or Last-Modified header value. 1670 // TODO(darin): Or should we use the last? 1671 1672 std::string etag_value; 1673 response_.headers->EnumerateHeader(NULL, "etag", &etag_value); 1674 1675 std::string last_modified_value; 1676 response_.headers->EnumerateHeader(NULL, "last-modified", 1677 &last_modified_value); 1678 1679 if (etag_value.empty() && last_modified_value.empty()) 1680 return false; 1681 1682 if (!partial_.get()) { 1683 // Need to customize the request, so this forces us to allocate :( 1684 custom_request_.reset(new HttpRequestInfo(*request_)); 1685 request_ = custom_request_.get(); 1686 } 1687 DCHECK(custom_request_.get()); 1688 1689 bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() && 1690 !invalid_range_; 1691 1692 if (!etag_value.empty()) { 1693 if (use_if_range) { 1694 // We don't want to switch to WRITE mode if we don't have this block of a 1695 // byte-range request because we may have other parts cached. 1696 custom_request_->extra_headers.SetHeader( 1697 HttpRequestHeaders::kIfRange, etag_value); 1698 } else { 1699 custom_request_->extra_headers.SetHeader( 1700 HttpRequestHeaders::kIfNoneMatch, etag_value); 1701 } 1702 // For byte-range requests, make sure that we use only one way to validate 1703 // the request. 1704 if (partial_.get() && !partial_->IsCurrentRangeCached()) 1705 return true; 1706 } 1707 1708 if (!last_modified_value.empty()) { 1709 if (use_if_range) { 1710 custom_request_->extra_headers.SetHeader( 1711 HttpRequestHeaders::kIfRange, last_modified_value); 1712 } else { 1713 custom_request_->extra_headers.SetHeader( 1714 HttpRequestHeaders::kIfModifiedSince, last_modified_value); 1715 } 1716 } 1717 1718 return true; 1719 } 1720 1721 // We just received some headers from the server. We may have asked for a range, 1722 // in which case partial_ has an object. This could be the first network request 1723 // we make to fulfill the original request, or we may be already reading (from 1724 // the net and / or the cache). If we are not expecting a certain response, we 1725 // just bypass the cache for this request (but again, maybe we are reading), and 1726 // delete partial_ (so we are not able to "fix" the headers that we return to 1727 // the user). This results in either a weird response for the caller (we don't 1728 // expect it after all), or maybe a range that was not exactly what it was asked 1729 // for. 1730 // 1731 // If the server is simply telling us that the resource has changed, we delete 1732 // the cached entry and restart the request as the caller intended (by returning 1733 // false from this method). However, we may not be able to do that at any point, 1734 // for instance if we already returned the headers to the user. 1735 // 1736 // WARNING: Whenever this code returns false, it has to make sure that the next 1737 // time it is called it will return true so that we don't keep retrying the 1738 // request. 1739 bool HttpCache::Transaction::ValidatePartialResponse(bool* partial_content) { 1740 const HttpResponseHeaders* headers = new_response_->headers; 1741 int response_code = headers->response_code(); 1742 bool partial_response = (response_code == 206); 1743 *partial_content = false; 1744 1745 if (!entry_) 1746 return true; 1747 1748 if (invalid_range_) { 1749 // We gave up trying to match this request with the stored data. If the 1750 // server is ok with the request, delete the entry, otherwise just ignore 1751 // this request 1752 DCHECK(!reading_); 1753 if (partial_response || response_code == 200) { 1754 DoomPartialEntry(true); 1755 mode_ = NONE; 1756 } else { 1757 if (response_code == 304) 1758 FailRangeRequest(); 1759 IgnoreRangeRequest(); 1760 } 1761 return true; 1762 } 1763 1764 if (!partial_.get()) { 1765 // We are not expecting 206 but we may have one. 1766 if (partial_response) 1767 IgnoreRangeRequest(); 1768 1769 return true; 1770 } 1771 1772 // TODO(rvargas): Do we need to consider other results here?. 1773 bool failure = response_code == 200 || response_code == 416; 1774 1775 if (partial_->IsCurrentRangeCached()) { 1776 // We asked for "If-None-Match: " so a 206 means a new object. 1777 if (partial_response) 1778 failure = true; 1779 1780 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) 1781 return true; 1782 } else { 1783 // We asked for "If-Range: " so a 206 means just another range. 1784 if (partial_response && partial_->ResponseHeadersOK(headers)) { 1785 *partial_content = true; 1786 return true; 1787 } 1788 1789 // 304 is not expected here, but we'll spare the entry (unless it was 1790 // truncated). 1791 if (truncated_) { 1792 if (!reading_ && response_code == 200) { 1793 // The server is sending the whole resource, and we can save it. 1794 DCHECK(!partial_->IsLastRange()); 1795 partial_.reset(); 1796 truncated_ = false; 1797 return true; 1798 } 1799 failure = true; 1800 } 1801 } 1802 1803 if (failure) { 1804 // We cannot truncate this entry, it has to be deleted. 1805 DoomPartialEntry(false); 1806 mode_ = NONE; 1807 if (!reading_ && !partial_->IsLastRange()) { 1808 // We'll attempt to issue another network request, this time without us 1809 // messing up the headers. 1810 partial_->RestoreHeaders(&custom_request_->extra_headers); 1811 partial_.reset(); 1812 truncated_ = false; 1813 return false; 1814 } 1815 LOG(WARNING) << "Failed to revalidate partial entry"; 1816 partial_.reset(); 1817 return true; 1818 } 1819 1820 IgnoreRangeRequest(); 1821 return true; 1822 } 1823 1824 void HttpCache::Transaction::IgnoreRangeRequest() { 1825 // We have a problem. We may or may not be reading already (in which case we 1826 // returned the headers), but we'll just pretend that this request is not 1827 // using the cache and see what happens. Most likely this is the first 1828 // response from the server (it's not changing its mind midway, right?). 1829 if (mode_ & WRITE) { 1830 DoneWritingToEntry(mode_ != WRITE); 1831 } else if (mode_ & READ && entry_) { 1832 cache_->DoneReadingFromEntry(entry_, this); 1833 } 1834 1835 partial_.reset(NULL); 1836 entry_ = NULL; 1837 mode_ = NONE; 1838 } 1839 1840 void HttpCache::Transaction::FailRangeRequest() { 1841 response_ = *new_response_; 1842 partial_->FixResponseHeaders(response_.headers, false); 1843 } 1844 1845 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { 1846 read_buf_ = data; 1847 io_buf_len_ = data_len; 1848 next_state_ = STATE_NETWORK_READ; 1849 return DoLoop(OK); 1850 } 1851 1852 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { 1853 read_buf_ = data; 1854 io_buf_len_ = data_len; 1855 next_state_ = STATE_CACHE_READ_DATA; 1856 return DoLoop(OK); 1857 } 1858 1859 int HttpCache::Transaction::WriteToEntry(int index, int offset, 1860 IOBuffer* data, int data_len, 1861 CompletionCallback* callback) { 1862 if (!entry_) 1863 return data_len; 1864 1865 int rv = 0; 1866 if (!partial_.get() || !data_len) { 1867 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, 1868 true); 1869 } else { 1870 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); 1871 } 1872 return rv; 1873 } 1874 1875 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { 1876 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1877 if (!entry_) 1878 return OK; 1879 1880 // Do not cache no-store content (unless we are record mode). Do not cache 1881 // content with cert errors either. This is to prevent not reporting net 1882 // errors when loading a resource from the cache. When we load a page over 1883 // HTTPS with a cert error we show an SSL blocking page. If the user clicks 1884 // proceed we reload the resource ignoring the errors. The loaded resource 1885 // is then cached. If that resource is subsequently loaded from the cache, 1886 // no net error is reported (even though the cert status contains the actual 1887 // errors) and no SSL blocking page is shown. An alternative would be to 1888 // reverse-map the cert status to a net error and replay the net error. 1889 if ((cache_->mode() != RECORD && 1890 response_.headers->HasHeaderValue("cache-control", "no-store")) || 1891 net::IsCertStatusError(response_.ssl_info.cert_status)) { 1892 DoneWritingToEntry(false); 1893 return OK; 1894 } 1895 1896 // When writing headers, we normally only write the non-transient 1897 // headers; when in record mode, record everything. 1898 bool skip_transient_headers = (cache_->mode() != RECORD); 1899 1900 if (truncated) { 1901 DCHECK_EQ(200, response_.headers->response_code()); 1902 } 1903 1904 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 1905 response_.Persist(data->pickle(), skip_transient_headers, truncated); 1906 data->Done(); 1907 1908 // Balanced in DoCacheWriteResponseComplete. We may be running from the 1909 // destructor of this object so cache_callback_ may be currently in use. 1910 write_headers_callback_->AddRef(); 1911 io_buf_len_ = data->pickle()->size(); 1912 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data, io_buf_len_, 1913 write_headers_callback_, true); 1914 } 1915 1916 int HttpCache::Transaction::AppendResponseDataToEntry( 1917 IOBuffer* data, int data_len, CompletionCallback* callback) { 1918 if (!entry_ || !data_len) 1919 return data_len; 1920 1921 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1922 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, 1923 callback); 1924 } 1925 1926 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 1927 if (!entry_) 1928 return; 1929 1930 if (cache_->mode() == RECORD) 1931 DVLOG(1) << "Recorded: " << request_->method << request_->url 1932 << " status: " << response_.headers->response_code(); 1933 1934 cache_->DoneWritingToEntry(entry_, success); 1935 entry_ = NULL; 1936 mode_ = NONE; // switch to 'pass through' mode 1937 } 1938 1939 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 1940 DVLOG(2) << "DoomPartialEntry"; 1941 int rv = cache_->DoomEntry(cache_key_, NULL); 1942 DCHECK_EQ(OK, rv); 1943 cache_->DoneWithEntry(entry_, this, false); 1944 entry_ = NULL; 1945 is_sparse_ = false; 1946 if (delete_object) 1947 partial_.reset(NULL); 1948 } 1949 1950 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { 1951 partial_->OnNetworkReadCompleted(result); 1952 1953 if (result == 0) { 1954 // We need to move on to the next range. 1955 network_trans_.reset(); 1956 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1957 } 1958 return result; 1959 } 1960 1961 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { 1962 partial_->OnCacheReadCompleted(result); 1963 1964 if (result == 0 && mode_ == READ_WRITE) { 1965 // We need to move on to the next range. 1966 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1967 } 1968 return result; 1969 } 1970 1971 // Histogram data from the end of 2010 show the following distribution of 1972 // response headers: 1973 // 1974 // Content-Length............... 87% 1975 // Date......................... 98% 1976 // Last-Modified................ 49% 1977 // Etag......................... 19% 1978 // Accept-Ranges: bytes......... 25% 1979 // Accept-Ranges: none.......... 0.4% 1980 // Strong Validator............. 50% 1981 // Strong Validator + ranges.... 24% 1982 // Strong Validator + CL........ 49% 1983 // 1984 bool HttpCache::Transaction::CanResume(bool has_data) { 1985 // Double check that there is something worth keeping. 1986 if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex)) 1987 return false; 1988 1989 if (request_->method != "GET") 1990 return false; 1991 1992 if (response_.headers->GetContentLength() <= 0 || 1993 response_.headers->HasHeaderValue("Accept-Ranges", "none") || 1994 !response_.headers->HasStrongValidators()) 1995 return false; 1996 1997 return true; 1998 } 1999 2000 void HttpCache::Transaction::OnIOComplete(int result) { 2001 DoLoop(result); 2002 } 2003 2004 } // namespace net 2005