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