1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 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 <algorithm> 14 #include <string> 15 16 #include "base/bind.h" 17 #include "base/compiler_specific.h" 18 #include "base/format_macros.h" 19 #include "base/memory/ref_counted.h" 20 #include "base/metrics/field_trial.h" 21 #include "base/metrics/histogram.h" 22 #include "base/metrics/sparse_histogram.h" 23 #include "base/rand_util.h" 24 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_piece.h" 26 #include "base/strings/string_util.h" 27 #include "base/strings/stringprintf.h" 28 #include "base/time/time.h" 29 #include "net/base/completion_callback.h" 30 #include "net/base/io_buffer.h" 31 #include "net/base/load_flags.h" 32 #include "net/base/load_timing_info.h" 33 #include "net/base/net_errors.h" 34 #include "net/base/net_log.h" 35 #include "net/base/upload_data_stream.h" 36 #include "net/cert/cert_status_flags.h" 37 #include "net/disk_cache/disk_cache.h" 38 #include "net/http/disk_based_cert_cache.h" 39 #include "net/http/http_network_session.h" 40 #include "net/http/http_request_info.h" 41 #include "net/http/http_response_headers.h" 42 #include "net/http/http_transaction.h" 43 #include "net/http/http_util.h" 44 #include "net/http/partial_data.h" 45 #include "net/ssl/ssl_cert_request_info.h" 46 #include "net/ssl/ssl_config_service.h" 47 48 using base::Time; 49 using base::TimeDelta; 50 using base::TimeTicks; 51 52 namespace { 53 54 // TODO(ricea): Move this to HttpResponseHeaders once it is standardised. 55 static const char kFreshnessHeader[] = "Resource-Freshness"; 56 57 // Stores data relevant to the statistics of writing and reading entire 58 // certificate chains using DiskBasedCertCache. |num_pending_ops| is the number 59 // of certificates in the chain that have pending operations in the 60 // DiskBasedCertCache. |start_time| is the time that the read and write 61 // commands began being issued to the DiskBasedCertCache. 62 // TODO(brandonsalmon): Remove this when it is no longer necessary to 63 // collect data. 64 class SharedChainData : public base::RefCounted<SharedChainData> { 65 public: 66 SharedChainData(int num_ops, TimeTicks start) 67 : num_pending_ops(num_ops), start_time(start) {} 68 69 int num_pending_ops; 70 TimeTicks start_time; 71 72 private: 73 friend class base::RefCounted<SharedChainData>; 74 ~SharedChainData() {} 75 DISALLOW_COPY_AND_ASSIGN(SharedChainData); 76 }; 77 78 // Used to obtain a cache entry key for an OSCertHandle. 79 // TODO(brandonsalmon): Remove this when cache keys are stored 80 // and no longer have to be recomputed to retrieve the OSCertHandle 81 // from the disk. 82 std::string GetCacheKeyForCert(net::X509Certificate::OSCertHandle cert_handle) { 83 net::SHA1HashValue fingerprint = 84 net::X509Certificate::CalculateFingerprint(cert_handle); 85 86 return "cert:" + 87 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); 88 } 89 90 // |dist_from_root| indicates the position of the read certificate in the 91 // certificate chain, 0 indicating it is the root. |is_leaf| indicates 92 // whether or not the read certificate was the leaf of the chain. 93 // |shared_chain_data| contains data shared by each certificate in 94 // the chain. 95 void OnCertReadIOComplete( 96 int dist_from_root, 97 bool is_leaf, 98 const scoped_refptr<SharedChainData>& shared_chain_data, 99 net::X509Certificate::OSCertHandle cert_handle) { 100 // If |num_pending_ops| is one, this was the last pending read operation 101 // for this chain of certificates. The total time used to read the chain 102 // can be calculated by subtracting the starting time from Now(). 103 shared_chain_data->num_pending_ops--; 104 if (!shared_chain_data->num_pending_ops) { 105 const TimeDelta read_chain_wait = 106 TimeTicks::Now() - shared_chain_data->start_time; 107 UMA_HISTOGRAM_CUSTOM_TIMES("DiskBasedCertCache.ChainReadTime", 108 read_chain_wait, 109 base::TimeDelta::FromMilliseconds(1), 110 base::TimeDelta::FromMinutes(10), 111 50); 112 } 113 114 bool success = (cert_handle != NULL); 115 if (is_leaf) 116 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.CertIoReadSuccessLeaf", success); 117 118 if (success) 119 UMA_HISTOGRAM_CUSTOM_COUNTS( 120 "DiskBasedCertCache.CertIoReadSuccess", dist_from_root, 0, 10, 7); 121 else 122 UMA_HISTOGRAM_CUSTOM_COUNTS( 123 "DiskBasedCertCache.CertIoReadFailure", dist_from_root, 0, 10, 7); 124 } 125 126 // |dist_from_root| indicates the position of the written certificate in the 127 // certificate chain, 0 indicating it is the root. |is_leaf| indicates 128 // whether or not the written certificate was the leaf of the chain. 129 // |shared_chain_data| contains data shared by each certificate in 130 // the chain. 131 void OnCertWriteIOComplete( 132 int dist_from_root, 133 bool is_leaf, 134 const scoped_refptr<SharedChainData>& shared_chain_data, 135 const std::string& key) { 136 // If |num_pending_ops| is one, this was the last pending write operation 137 // for this chain of certificates. The total time used to write the chain 138 // can be calculated by subtracting the starting time from Now(). 139 shared_chain_data->num_pending_ops--; 140 if (!shared_chain_data->num_pending_ops) { 141 const TimeDelta write_chain_wait = 142 TimeTicks::Now() - shared_chain_data->start_time; 143 UMA_HISTOGRAM_CUSTOM_TIMES("DiskBasedCertCache.ChainWriteTime", 144 write_chain_wait, 145 base::TimeDelta::FromMilliseconds(1), 146 base::TimeDelta::FromMinutes(10), 147 50); 148 } 149 150 bool success = !key.empty(); 151 if (is_leaf) 152 UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.CertIoWriteSuccessLeaf", success); 153 154 if (success) 155 UMA_HISTOGRAM_CUSTOM_COUNTS( 156 "DiskBasedCertCache.CertIoWriteSuccess", dist_from_root, 0, 10, 7); 157 else 158 UMA_HISTOGRAM_CUSTOM_COUNTS( 159 "DiskBasedCertCache.CertIoWriteFailure", dist_from_root, 0, 10, 7); 160 } 161 162 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 163 // a "non-error response" is one with a 2xx (Successful) or 3xx 164 // (Redirection) status code. 165 bool NonErrorResponse(int status_code) { 166 int status_code_range = status_code / 100; 167 return status_code_range == 2 || status_code_range == 3; 168 } 169 170 // Error codes that will be considered indicative of a page being offline/ 171 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE. 172 bool IsOfflineError(int error) { 173 return (error == net::ERR_NAME_NOT_RESOLVED || 174 error == net::ERR_INTERNET_DISCONNECTED || 175 error == net::ERR_ADDRESS_UNREACHABLE || 176 error == net::ERR_CONNECTION_TIMED_OUT); 177 } 178 179 // Enum for UMA, indicating the status (with regard to offline mode) of 180 // a particular request. 181 enum RequestOfflineStatus { 182 // A cache transaction hit in cache (data was present and not stale) 183 // and returned it. 184 OFFLINE_STATUS_FRESH_CACHE, 185 186 // A network request was required for a cache entry, and it succeeded. 187 OFFLINE_STATUS_NETWORK_SUCCEEDED, 188 189 // A network request was required for a cache entry, and it failed with 190 // a non-offline error. 191 OFFLINE_STATUS_NETWORK_FAILED, 192 193 // A network request was required for a cache entry, it failed with an 194 // offline error, and we could serve stale data if 195 // LOAD_FROM_CACHE_IF_OFFLINE was set. 196 OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE, 197 198 // A network request was required for a cache entry, it failed with 199 // an offline error, and there was no servable data in cache (even 200 // stale data). 201 OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE, 202 203 OFFLINE_STATUS_MAX_ENTRIES 204 }; 205 206 void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) { 207 // Restrict to main frame to keep statistics close to 208 // "would have shown them something useful if offline mode was enabled". 209 if (load_flags & net::LOAD_MAIN_FRAME) { 210 UMA_HISTOGRAM_ENUMERATION("HttpCache.OfflineStatus", status, 211 OFFLINE_STATUS_MAX_ENTRIES); 212 } 213 } 214 215 // TODO(rvargas): Remove once we get the data. 216 void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) { 217 enum VaryType { 218 VARY_NOT_PRESENT, 219 VARY_UA, 220 VARY_OTHER, 221 VARY_MAX 222 }; 223 VaryType vary = VARY_NOT_PRESENT; 224 if (response->vary_data.is_valid()) { 225 vary = VARY_OTHER; 226 if (response->headers->HasHeaderValue("vary", "user-agent")) 227 vary = VARY_UA; 228 } 229 UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX); 230 } 231 232 void RecordNoStoreHeaderHistogram(int load_flags, 233 const net::HttpResponseInfo* response) { 234 if (load_flags & net::LOAD_MAIN_FRAME) { 235 UMA_HISTOGRAM_BOOLEAN( 236 "Net.MainFrameNoStore", 237 response->headers->HasHeaderValue("cache-control", "no-store")); 238 } 239 } 240 241 enum ExternallyConditionalizedType { 242 EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION, 243 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE, 244 EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS, 245 EXTERNALLY_CONDITIONALIZED_MAX 246 }; 247 248 } // namespace 249 250 namespace net { 251 252 struct HeaderNameAndValue { 253 const char* name; 254 const char* value; 255 }; 256 257 // If the request includes one of these request headers, then avoid caching 258 // to avoid getting confused. 259 static const HeaderNameAndValue kPassThroughHeaders[] = { 260 { "if-unmodified-since", NULL }, // causes unexpected 412s 261 { "if-match", NULL }, // causes unexpected 412s 262 { "if-range", NULL }, 263 { NULL, NULL } 264 }; 265 266 struct ValidationHeaderInfo { 267 const char* request_header_name; 268 const char* related_response_header_name; 269 }; 270 271 static const ValidationHeaderInfo kValidationHeaders[] = { 272 { "if-modified-since", "last-modified" }, 273 { "if-none-match", "etag" }, 274 }; 275 276 // If the request includes one of these request headers, then avoid reusing 277 // our cached copy if any. 278 static const HeaderNameAndValue kForceFetchHeaders[] = { 279 { "cache-control", "no-cache" }, 280 { "pragma", "no-cache" }, 281 { NULL, NULL } 282 }; 283 284 // If the request includes one of these request headers, then force our 285 // cached copy (if any) to be revalidated before reusing it. 286 static const HeaderNameAndValue kForceValidateHeaders[] = { 287 { "cache-control", "max-age=0" }, 288 { NULL, NULL } 289 }; 290 291 static bool HeaderMatches(const HttpRequestHeaders& headers, 292 const HeaderNameAndValue* search) { 293 for (; search->name; ++search) { 294 std::string header_value; 295 if (!headers.GetHeader(search->name, &header_value)) 296 continue; 297 298 if (!search->value) 299 return true; 300 301 HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ','); 302 while (v.GetNext()) { 303 if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value)) 304 return true; 305 } 306 } 307 return false; 308 } 309 310 //----------------------------------------------------------------------------- 311 312 HttpCache::Transaction::Transaction( 313 RequestPriority priority, 314 HttpCache* cache) 315 : next_state_(STATE_NONE), 316 request_(NULL), 317 priority_(priority), 318 cache_(cache->GetWeakPtr()), 319 entry_(NULL), 320 new_entry_(NULL), 321 new_response_(NULL), 322 mode_(NONE), 323 target_state_(STATE_NONE), 324 reading_(false), 325 invalid_range_(false), 326 truncated_(false), 327 is_sparse_(false), 328 range_requested_(false), 329 handling_206_(false), 330 cache_pending_(false), 331 done_reading_(false), 332 vary_mismatch_(false), 333 couldnt_conditionalize_request_(false), 334 bypass_lock_for_test_(false), 335 io_buf_len_(0), 336 read_offset_(0), 337 effective_load_flags_(0), 338 write_len_(0), 339 transaction_pattern_(PATTERN_UNDEFINED), 340 total_received_bytes_(0), 341 websocket_handshake_stream_base_create_helper_(NULL), 342 weak_factory_(this) { 343 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == 344 arraysize(kValidationHeaders), 345 Invalid_number_of_validation_headers); 346 347 io_callback_ = base::Bind(&Transaction::OnIOComplete, 348 weak_factory_.GetWeakPtr()); 349 } 350 351 HttpCache::Transaction::~Transaction() { 352 // We may have to issue another IO, but we should never invoke the callback_ 353 // after this point. 354 callback_.Reset(); 355 356 if (cache_) { 357 if (entry_) { 358 bool cancel_request = reading_ && response_.headers.get(); 359 if (cancel_request) { 360 if (partial_) { 361 entry_->disk_entry->CancelSparseIO(); 362 } else { 363 cancel_request &= (response_.headers->response_code() == 200); 364 } 365 } 366 367 cache_->DoneWithEntry(entry_, this, cancel_request); 368 } else if (cache_pending_) { 369 cache_->RemovePendingTransaction(this); 370 } 371 } 372 } 373 374 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 375 const CompletionCallback& callback) { 376 DCHECK(buf); 377 DCHECK_GT(buf_len, 0); 378 DCHECK(!callback.is_null()); 379 if (!cache_.get() || !entry_) 380 return ERR_UNEXPECTED; 381 382 // We don't need to track this operation for anything. 383 // It could be possible to check if there is something already written and 384 // avoid writing again (it should be the same, right?), but let's allow the 385 // caller to "update" the contents with something new. 386 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 387 callback, true); 388 } 389 390 bool HttpCache::Transaction::AddTruncatedFlag() { 391 DCHECK(mode_ & WRITE || mode_ == NONE); 392 393 // Don't set the flag for sparse entries. 394 if (partial_.get() && !truncated_) 395 return true; 396 397 if (!CanResume(true)) 398 return false; 399 400 // We may have received the whole resource already. 401 if (done_reading_) 402 return true; 403 404 truncated_ = true; 405 target_state_ = STATE_NONE; 406 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; 407 DoLoop(OK); 408 return true; 409 } 410 411 LoadState HttpCache::Transaction::GetWriterLoadState() const { 412 if (network_trans_.get()) 413 return network_trans_->GetLoadState(); 414 if (entry_ || !request_) 415 return LOAD_STATE_IDLE; 416 return LOAD_STATE_WAITING_FOR_CACHE; 417 } 418 419 const BoundNetLog& HttpCache::Transaction::net_log() const { 420 return net_log_; 421 } 422 423 int HttpCache::Transaction::Start(const HttpRequestInfo* request, 424 const CompletionCallback& callback, 425 const BoundNetLog& net_log) { 426 DCHECK(request); 427 DCHECK(!callback.is_null()); 428 429 // Ensure that we only have one asynchronous call at a time. 430 DCHECK(callback_.is_null()); 431 DCHECK(!reading_); 432 DCHECK(!network_trans_.get()); 433 DCHECK(!entry_); 434 435 if (!cache_.get()) 436 return ERR_UNEXPECTED; 437 438 SetRequest(net_log, request); 439 440 // We have to wait until the backend is initialized so we start the SM. 441 next_state_ = STATE_GET_BACKEND; 442 int rv = DoLoop(OK); 443 444 // Setting this here allows us to check for the existence of a callback_ to 445 // determine if we are still inside Start. 446 if (rv == ERR_IO_PENDING) 447 callback_ = callback; 448 449 return rv; 450 } 451 452 int HttpCache::Transaction::RestartIgnoringLastError( 453 const CompletionCallback& callback) { 454 DCHECK(!callback.is_null()); 455 456 // Ensure that we only have one asynchronous call at a time. 457 DCHECK(callback_.is_null()); 458 459 if (!cache_.get()) 460 return ERR_UNEXPECTED; 461 462 int rv = RestartNetworkRequest(); 463 464 if (rv == ERR_IO_PENDING) 465 callback_ = callback; 466 467 return rv; 468 } 469 470 int HttpCache::Transaction::RestartWithCertificate( 471 X509Certificate* client_cert, 472 const CompletionCallback& callback) { 473 DCHECK(!callback.is_null()); 474 475 // Ensure that we only have one asynchronous call at a time. 476 DCHECK(callback_.is_null()); 477 478 if (!cache_.get()) 479 return ERR_UNEXPECTED; 480 481 int rv = RestartNetworkRequestWithCertificate(client_cert); 482 483 if (rv == ERR_IO_PENDING) 484 callback_ = callback; 485 486 return rv; 487 } 488 489 int HttpCache::Transaction::RestartWithAuth( 490 const AuthCredentials& credentials, 491 const CompletionCallback& callback) { 492 DCHECK(auth_response_.headers.get()); 493 DCHECK(!callback.is_null()); 494 495 // Ensure that we only have one asynchronous call at a time. 496 DCHECK(callback_.is_null()); 497 498 if (!cache_.get()) 499 return ERR_UNEXPECTED; 500 501 // Clear the intermediate response since we are going to start over. 502 auth_response_ = HttpResponseInfo(); 503 504 int rv = RestartNetworkRequestWithAuth(credentials); 505 506 if (rv == ERR_IO_PENDING) 507 callback_ = callback; 508 509 return rv; 510 } 511 512 bool HttpCache::Transaction::IsReadyToRestartForAuth() { 513 if (!network_trans_.get()) 514 return false; 515 return network_trans_->IsReadyToRestartForAuth(); 516 } 517 518 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 519 const CompletionCallback& callback) { 520 DCHECK(buf); 521 DCHECK_GT(buf_len, 0); 522 DCHECK(!callback.is_null()); 523 524 DCHECK(callback_.is_null()); 525 526 if (!cache_.get()) 527 return ERR_UNEXPECTED; 528 529 // If we have an intermediate auth response at this point, then it means the 530 // user wishes to read the network response (the error page). If there is a 531 // previous response in the cache then we should leave it intact. 532 if (auth_response_.headers.get() && mode_ != NONE) { 533 UpdateTransactionPattern(PATTERN_NOT_COVERED); 534 DCHECK(mode_ & WRITE); 535 DoneWritingToEntry(mode_ == READ_WRITE); 536 mode_ = NONE; 537 } 538 539 reading_ = true; 540 int rv; 541 542 switch (mode_) { 543 case READ_WRITE: 544 DCHECK(partial_.get()); 545 if (!network_trans_.get()) { 546 // We are just reading from the cache, but we may be writing later. 547 rv = ReadFromEntry(buf, buf_len); 548 break; 549 } 550 case NONE: 551 case WRITE: 552 DCHECK(network_trans_.get()); 553 rv = ReadFromNetwork(buf, buf_len); 554 break; 555 case READ: 556 rv = ReadFromEntry(buf, buf_len); 557 break; 558 default: 559 NOTREACHED(); 560 rv = ERR_FAILED; 561 } 562 563 if (rv == ERR_IO_PENDING) { 564 DCHECK(callback_.is_null()); 565 callback_ = callback; 566 } 567 return rv; 568 } 569 570 void HttpCache::Transaction::StopCaching() { 571 // We really don't know where we are now. Hopefully there is no operation in 572 // progress, but nothing really prevents this method to be called after we 573 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this 574 // point because we need the state machine for that (and even if we are really 575 // free, that would be an asynchronous operation). In other words, keep the 576 // entry how it is (it will be marked as truncated at destruction), and let 577 // the next piece of code that executes know that we are now reading directly 578 // from the net. 579 // TODO(mmenke): This doesn't release the lock on the cache entry, so a 580 // future request for the resource will be blocked on this one. 581 // Fix this. 582 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() && 583 !is_sparse_ && !range_requested_) { 584 mode_ = NONE; 585 } 586 } 587 588 bool HttpCache::Transaction::GetFullRequestHeaders( 589 HttpRequestHeaders* headers) const { 590 if (network_trans_) 591 return network_trans_->GetFullRequestHeaders(headers); 592 593 // TODO(ttuttle): Read headers from cache. 594 return false; 595 } 596 597 int64 HttpCache::Transaction::GetTotalReceivedBytes() const { 598 int64 total_received_bytes = total_received_bytes_; 599 if (network_trans_) 600 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 601 return total_received_bytes; 602 } 603 604 void HttpCache::Transaction::DoneReading() { 605 if (cache_.get() && entry_) { 606 DCHECK_NE(mode_, UPDATE); 607 if (mode_ & WRITE) { 608 DoneWritingToEntry(true); 609 } else if (mode_ & READ) { 610 // It is necessary to check mode_ & READ because it is possible 611 // for mode_ to be NONE and entry_ non-NULL with a write entry 612 // if StopCaching was called. 613 cache_->DoneReadingFromEntry(entry_, this); 614 entry_ = NULL; 615 } 616 } 617 } 618 619 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const { 620 // Null headers means we encountered an error or haven't a response yet 621 if (auth_response_.headers.get()) 622 return &auth_response_; 623 return (response_.headers.get() || response_.ssl_info.cert.get() || 624 response_.cert_request_info.get()) 625 ? &response_ 626 : NULL; 627 } 628 629 LoadState HttpCache::Transaction::GetLoadState() const { 630 LoadState state = GetWriterLoadState(); 631 if (state != LOAD_STATE_WAITING_FOR_CACHE) 632 return state; 633 634 if (cache_.get()) 635 return cache_->GetLoadStateForPendingTransaction(this); 636 637 return LOAD_STATE_IDLE; 638 } 639 640 UploadProgress HttpCache::Transaction::GetUploadProgress() const { 641 if (network_trans_.get()) 642 return network_trans_->GetUploadProgress(); 643 return final_upload_progress_; 644 } 645 646 void HttpCache::Transaction::SetQuicServerInfo( 647 QuicServerInfo* quic_server_info) {} 648 649 bool HttpCache::Transaction::GetLoadTimingInfo( 650 LoadTimingInfo* load_timing_info) const { 651 if (network_trans_) 652 return network_trans_->GetLoadTimingInfo(load_timing_info); 653 654 if (old_network_trans_load_timing_) { 655 *load_timing_info = *old_network_trans_load_timing_; 656 return true; 657 } 658 659 if (first_cache_access_since_.is_null()) 660 return false; 661 662 // If the cache entry was opened, return that time. 663 load_timing_info->send_start = first_cache_access_since_; 664 // This time doesn't make much sense when reading from the cache, so just use 665 // the same time as send_start. 666 load_timing_info->send_end = first_cache_access_since_; 667 return true; 668 } 669 670 void HttpCache::Transaction::SetPriority(RequestPriority priority) { 671 priority_ = priority; 672 if (network_trans_) 673 network_trans_->SetPriority(priority_); 674 } 675 676 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper( 677 WebSocketHandshakeStreamBase::CreateHelper* create_helper) { 678 websocket_handshake_stream_base_create_helper_ = create_helper; 679 if (network_trans_) 680 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper); 681 } 682 683 void HttpCache::Transaction::SetBeforeNetworkStartCallback( 684 const BeforeNetworkStartCallback& callback) { 685 DCHECK(!network_trans_); 686 before_network_start_callback_ = callback; 687 } 688 689 void HttpCache::Transaction::SetBeforeProxyHeadersSentCallback( 690 const BeforeProxyHeadersSentCallback& callback) { 691 DCHECK(!network_trans_); 692 before_proxy_headers_sent_callback_ = callback; 693 } 694 695 int HttpCache::Transaction::ResumeNetworkStart() { 696 if (network_trans_) 697 return network_trans_->ResumeNetworkStart(); 698 return ERR_UNEXPECTED; 699 } 700 701 //----------------------------------------------------------------------------- 702 703 void HttpCache::Transaction::DoCallback(int rv) { 704 DCHECK(rv != ERR_IO_PENDING); 705 DCHECK(!callback_.is_null()); 706 707 read_buf_ = NULL; // Release the buffer before invoking the callback. 708 709 // Since Run may result in Read being called, clear callback_ up front. 710 CompletionCallback c = callback_; 711 callback_.Reset(); 712 c.Run(rv); 713 } 714 715 int HttpCache::Transaction::HandleResult(int rv) { 716 DCHECK(rv != ERR_IO_PENDING); 717 if (!callback_.is_null()) 718 DoCallback(rv); 719 720 return rv; 721 } 722 723 // A few common patterns: (Foo* means Foo -> FooComplete) 724 // 725 // 1. Not-cached entry: 726 // Start(): 727 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* -> 728 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> 729 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* -> 730 // PartialHeadersReceived 731 // 732 // Read(): 733 // NetworkRead* -> CacheWriteData* 734 // 735 // 2. Cached entry, no validation: 736 // Start(): 737 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 738 // -> BeginPartialCacheValidation() -> BeginCacheValidation() -> 739 // SetupEntryForRead() 740 // 741 // Read(): 742 // CacheReadData* 743 // 744 // 3. Cached entry, validation (304): 745 // Start(): 746 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 747 // -> BeginPartialCacheValidation() -> BeginCacheValidation() -> 748 // SendRequest* -> SuccessfulSendRequest -> UpdateCachedResponse -> 749 // CacheWriteResponse* -> UpdateCachedResponseComplete -> 750 // OverwriteCachedResponse -> PartialHeadersReceived 751 // 752 // Read(): 753 // CacheReadData* 754 // 755 // 4. Cached entry, validation and replace (200): 756 // Start(): 757 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 758 // -> BeginPartialCacheValidation() -> BeginCacheValidation() -> 759 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> 760 // CacheWriteResponse* -> DoTruncateCachedData* -> TruncateCachedMetadata* -> 761 // PartialHeadersReceived 762 // 763 // Read(): 764 // NetworkRead* -> CacheWriteData* 765 // 766 // 5. Sparse entry, partially cached, byte range request: 767 // Start(): 768 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 769 // -> BeginPartialCacheValidation() -> CacheQueryData* -> 770 // ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation -> 771 // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* -> 772 // SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteResponse* -> 773 // UpdateCachedResponseComplete -> OverwriteCachedResponse -> 774 // PartialHeadersReceived 775 // 776 // Read() 1: 777 // NetworkRead* -> CacheWriteData* 778 // 779 // Read() 2: 780 // NetworkRead* -> CacheWriteData* -> StartPartialCacheValidation -> 781 // CompletePartialCacheValidation -> CacheReadData* -> 782 // 783 // Read() 3: 784 // CacheReadData* -> StartPartialCacheValidation -> 785 // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* -> 786 // SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse 787 // -> PartialHeadersReceived -> NetworkRead* -> CacheWriteData* 788 // 789 // 6. HEAD. Not-cached entry: 790 // Pass through. Don't save a HEAD by itself. 791 // Start(): 792 // GetBackend* -> InitEntry -> OpenEntry* -> SendRequest* 793 // 794 // 7. HEAD. Cached entry, no validation: 795 // Start(): 796 // The same flow as for a GET request (example #2) 797 // 798 // Read(): 799 // CacheReadData (returns 0) 800 // 801 // 8. HEAD. Cached entry, validation (304): 802 // The request updates the stored headers. 803 // Start(): Same as for a GET request (example #3) 804 // 805 // Read(): 806 // CacheReadData (returns 0) 807 // 808 // 9. HEAD. Cached entry, validation and replace (200): 809 // Pass through. The request dooms the old entry, as a HEAD won't be stored by 810 // itself. 811 // Start(): 812 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 813 // -> BeginPartialCacheValidation() -> BeginCacheValidation() -> 814 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse 815 // 816 // 10. HEAD. Sparse entry, partially cached: 817 // Serve the request from the cache, as long as it doesn't require 818 // revalidation. Ignore missing ranges when deciding to revalidate. If the 819 // entry requires revalidation, ignore the whole request and go to full pass 820 // through (the result of the HEAD request will NOT update the entry). 821 // 822 // Start(): Basically the same as example 7, as we never create a partial_ 823 // object for this request. 824 // 825 int HttpCache::Transaction::DoLoop(int result) { 826 DCHECK(next_state_ != STATE_NONE); 827 828 int rv = result; 829 do { 830 State state = next_state_; 831 next_state_ = STATE_NONE; 832 switch (state) { 833 case STATE_GET_BACKEND: 834 DCHECK_EQ(OK, rv); 835 rv = DoGetBackend(); 836 break; 837 case STATE_GET_BACKEND_COMPLETE: 838 rv = DoGetBackendComplete(rv); 839 break; 840 case STATE_SEND_REQUEST: 841 DCHECK_EQ(OK, rv); 842 rv = DoSendRequest(); 843 break; 844 case STATE_SEND_REQUEST_COMPLETE: 845 rv = DoSendRequestComplete(rv); 846 break; 847 case STATE_SUCCESSFUL_SEND_REQUEST: 848 DCHECK_EQ(OK, rv); 849 rv = DoSuccessfulSendRequest(); 850 break; 851 case STATE_NETWORK_READ: 852 DCHECK_EQ(OK, rv); 853 rv = DoNetworkRead(); 854 break; 855 case STATE_NETWORK_READ_COMPLETE: 856 rv = DoNetworkReadComplete(rv); 857 break; 858 case STATE_INIT_ENTRY: 859 DCHECK_EQ(OK, rv); 860 rv = DoInitEntry(); 861 break; 862 case STATE_OPEN_ENTRY: 863 DCHECK_EQ(OK, rv); 864 rv = DoOpenEntry(); 865 break; 866 case STATE_OPEN_ENTRY_COMPLETE: 867 rv = DoOpenEntryComplete(rv); 868 break; 869 case STATE_CREATE_ENTRY: 870 DCHECK_EQ(OK, rv); 871 rv = DoCreateEntry(); 872 break; 873 case STATE_CREATE_ENTRY_COMPLETE: 874 rv = DoCreateEntryComplete(rv); 875 break; 876 case STATE_DOOM_ENTRY: 877 DCHECK_EQ(OK, rv); 878 rv = DoDoomEntry(); 879 break; 880 case STATE_DOOM_ENTRY_COMPLETE: 881 rv = DoDoomEntryComplete(rv); 882 break; 883 case STATE_ADD_TO_ENTRY: 884 DCHECK_EQ(OK, rv); 885 rv = DoAddToEntry(); 886 break; 887 case STATE_ADD_TO_ENTRY_COMPLETE: 888 rv = DoAddToEntryComplete(rv); 889 break; 890 case STATE_START_PARTIAL_CACHE_VALIDATION: 891 DCHECK_EQ(OK, rv); 892 rv = DoStartPartialCacheValidation(); 893 break; 894 case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION: 895 rv = DoCompletePartialCacheValidation(rv); 896 break; 897 case STATE_UPDATE_CACHED_RESPONSE: 898 DCHECK_EQ(OK, rv); 899 rv = DoUpdateCachedResponse(); 900 break; 901 case STATE_UPDATE_CACHED_RESPONSE_COMPLETE: 902 rv = DoUpdateCachedResponseComplete(rv); 903 break; 904 case STATE_OVERWRITE_CACHED_RESPONSE: 905 DCHECK_EQ(OK, rv); 906 rv = DoOverwriteCachedResponse(); 907 break; 908 case STATE_TRUNCATE_CACHED_DATA: 909 DCHECK_EQ(OK, rv); 910 rv = DoTruncateCachedData(); 911 break; 912 case STATE_TRUNCATE_CACHED_DATA_COMPLETE: 913 rv = DoTruncateCachedDataComplete(rv); 914 break; 915 case STATE_TRUNCATE_CACHED_METADATA: 916 DCHECK_EQ(OK, rv); 917 rv = DoTruncateCachedMetadata(); 918 break; 919 case STATE_TRUNCATE_CACHED_METADATA_COMPLETE: 920 rv = DoTruncateCachedMetadataComplete(rv); 921 break; 922 case STATE_PARTIAL_HEADERS_RECEIVED: 923 DCHECK_EQ(OK, rv); 924 rv = DoPartialHeadersReceived(); 925 break; 926 case STATE_CACHE_READ_RESPONSE: 927 DCHECK_EQ(OK, rv); 928 rv = DoCacheReadResponse(); 929 break; 930 case STATE_CACHE_READ_RESPONSE_COMPLETE: 931 rv = DoCacheReadResponseComplete(rv); 932 break; 933 case STATE_CACHE_WRITE_RESPONSE: 934 DCHECK_EQ(OK, rv); 935 rv = DoCacheWriteResponse(); 936 break; 937 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: 938 DCHECK_EQ(OK, rv); 939 rv = DoCacheWriteTruncatedResponse(); 940 break; 941 case STATE_CACHE_WRITE_RESPONSE_COMPLETE: 942 rv = DoCacheWriteResponseComplete(rv); 943 break; 944 case STATE_CACHE_READ_METADATA: 945 DCHECK_EQ(OK, rv); 946 rv = DoCacheReadMetadata(); 947 break; 948 case STATE_CACHE_READ_METADATA_COMPLETE: 949 rv = DoCacheReadMetadataComplete(rv); 950 break; 951 case STATE_CACHE_QUERY_DATA: 952 DCHECK_EQ(OK, rv); 953 rv = DoCacheQueryData(); 954 break; 955 case STATE_CACHE_QUERY_DATA_COMPLETE: 956 rv = DoCacheQueryDataComplete(rv); 957 break; 958 case STATE_CACHE_READ_DATA: 959 DCHECK_EQ(OK, rv); 960 rv = DoCacheReadData(); 961 break; 962 case STATE_CACHE_READ_DATA_COMPLETE: 963 rv = DoCacheReadDataComplete(rv); 964 break; 965 case STATE_CACHE_WRITE_DATA: 966 rv = DoCacheWriteData(rv); 967 break; 968 case STATE_CACHE_WRITE_DATA_COMPLETE: 969 rv = DoCacheWriteDataComplete(rv); 970 break; 971 default: 972 NOTREACHED() << "bad state"; 973 rv = ERR_FAILED; 974 break; 975 } 976 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 977 978 if (rv != ERR_IO_PENDING) 979 HandleResult(rv); 980 981 return rv; 982 } 983 984 int HttpCache::Transaction::DoGetBackend() { 985 cache_pending_ = true; 986 next_state_ = STATE_GET_BACKEND_COMPLETE; 987 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND); 988 return cache_->GetBackendForTransaction(this); 989 } 990 991 int HttpCache::Transaction::DoGetBackendComplete(int result) { 992 DCHECK(result == OK || result == ERR_FAILED); 993 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND, 994 result); 995 cache_pending_ = false; 996 997 if (!ShouldPassThrough()) { 998 cache_key_ = cache_->GenerateCacheKey(request_); 999 1000 // Requested cache access mode. 1001 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { 1002 mode_ = READ; 1003 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { 1004 mode_ = WRITE; 1005 } else { 1006 mode_ = READ_WRITE; 1007 } 1008 1009 // Downgrade to UPDATE if the request has been externally conditionalized. 1010 if (external_validation_.initialized) { 1011 if (mode_ & WRITE) { 1012 // Strip off the READ_DATA bit (and maybe add back a READ_META bit 1013 // in case READ was off). 1014 mode_ = UPDATE; 1015 } else { 1016 mode_ = NONE; 1017 } 1018 } 1019 } 1020 1021 // Use PUT and DELETE only to invalidate existing stored entries. 1022 if ((request_->method == "PUT" || request_->method == "DELETE") && 1023 mode_ != READ_WRITE && mode_ != WRITE) { 1024 mode_ = NONE; 1025 } 1026 1027 // Note that if mode_ == UPDATE (which is tied to external_validation_), the 1028 // transaction behaves the same for GET and HEAD requests at this point: if it 1029 // was not modified, the entry is updated and a response is not returned from 1030 // the cache. If we receive 200, it doesn't matter if there was a validation 1031 // header or not. 1032 if (request_->method == "HEAD" && mode_ == WRITE) 1033 mode_ = NONE; 1034 1035 // If must use cache, then we must fail. This can happen for back/forward 1036 // navigations to a page generated via a form post. 1037 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) 1038 return ERR_CACHE_MISS; 1039 1040 if (mode_ == NONE) { 1041 if (partial_.get()) { 1042 partial_->RestoreHeaders(&custom_request_->extra_headers); 1043 partial_.reset(); 1044 } 1045 next_state_ = STATE_SEND_REQUEST; 1046 } else { 1047 next_state_ = STATE_INIT_ENTRY; 1048 } 1049 1050 // This is only set if we have something to do with the response. 1051 range_requested_ = (partial_.get() != NULL); 1052 1053 return OK; 1054 } 1055 1056 int HttpCache::Transaction::DoSendRequest() { 1057 DCHECK(mode_ & WRITE || mode_ == NONE); 1058 DCHECK(!network_trans_.get()); 1059 1060 send_request_since_ = TimeTicks::Now(); 1061 1062 // Create a network transaction. 1063 int rv = cache_->network_layer_->CreateTransaction(priority_, 1064 &network_trans_); 1065 if (rv != OK) 1066 return rv; 1067 network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_); 1068 network_trans_->SetBeforeProxyHeadersSentCallback( 1069 before_proxy_headers_sent_callback_); 1070 1071 // Old load timing information, if any, is now obsolete. 1072 old_network_trans_load_timing_.reset(); 1073 1074 if (websocket_handshake_stream_base_create_helper_) 1075 network_trans_->SetWebSocketHandshakeStreamCreateHelper( 1076 websocket_handshake_stream_base_create_helper_); 1077 1078 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1079 rv = network_trans_->Start(request_, io_callback_, net_log_); 1080 return rv; 1081 } 1082 1083 int HttpCache::Transaction::DoSendRequestComplete(int result) { 1084 if (!cache_.get()) 1085 return ERR_UNEXPECTED; 1086 1087 // If requested, and we have a readable cache entry, and we have 1088 // an error indicating that we're offline as opposed to in contact 1089 // with a bad server, read from cache anyway. 1090 if (IsOfflineError(result)) { 1091 if (mode_ == READ_WRITE && entry_ && !partial_) { 1092 RecordOfflineStatus(effective_load_flags_, 1093 OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE); 1094 if (effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) { 1095 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1096 response_.server_data_unavailable = true; 1097 return SetupEntryForRead(); 1098 } 1099 } else { 1100 RecordOfflineStatus(effective_load_flags_, 1101 OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE); 1102 } 1103 } else { 1104 RecordOfflineStatus(effective_load_flags_, 1105 (result == OK ? OFFLINE_STATUS_NETWORK_SUCCEEDED : 1106 OFFLINE_STATUS_NETWORK_FAILED)); 1107 } 1108 1109 // If we tried to conditionalize the request and failed, we know 1110 // we won't be reading from the cache after this point. 1111 if (couldnt_conditionalize_request_) 1112 mode_ = WRITE; 1113 1114 if (result == OK) { 1115 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 1116 return OK; 1117 } 1118 1119 // Do not record requests that have network errors or restarts. 1120 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1121 if (IsCertificateError(result)) { 1122 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 1123 // If we get a certificate error, then there is a certificate in ssl_info, 1124 // so GetResponseInfo() should never return NULL here. 1125 DCHECK(response); 1126 response_.ssl_info = response->ssl_info; 1127 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 1128 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 1129 DCHECK(response); 1130 response_.cert_request_info = response->cert_request_info; 1131 } else if (response_.was_cached) { 1132 DoneWritingToEntry(true); 1133 } 1134 return result; 1135 } 1136 1137 // We received the response headers and there is no error. 1138 int HttpCache::Transaction::DoSuccessfulSendRequest() { 1139 DCHECK(!new_response_); 1140 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); 1141 bool authentication_failure = false; 1142 1143 if (new_response->headers->response_code() == 401 || 1144 new_response->headers->response_code() == 407) { 1145 auth_response_ = *new_response; 1146 if (!reading_) 1147 return OK; 1148 1149 // We initiated a second request the caller doesn't know about. We should be 1150 // able to authenticate this request because we should have authenticated 1151 // this URL moments ago. 1152 if (IsReadyToRestartForAuth()) { 1153 DCHECK(!response_.auth_challenge.get()); 1154 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1155 // In theory we should check to see if there are new cookies, but there 1156 // is no way to do that from here. 1157 return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_); 1158 } 1159 1160 // We have to perform cleanup at this point so that at least the next 1161 // request can succeed. 1162 authentication_failure = true; 1163 if (entry_) 1164 DoomPartialEntry(false); 1165 mode_ = NONE; 1166 partial_.reset(); 1167 } 1168 1169 new_response_ = new_response; 1170 if (authentication_failure || 1171 (!ValidatePartialResponse() && !auth_response_.headers.get())) { 1172 // Something went wrong with this request and we have to restart it. 1173 // If we have an authentication response, we are exposed to weird things 1174 // hapenning if the user cancels the authentication before we receive 1175 // the new response. 1176 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1177 response_ = HttpResponseInfo(); 1178 ResetNetworkTransaction(); 1179 new_response_ = NULL; 1180 next_state_ = STATE_SEND_REQUEST; 1181 return OK; 1182 } 1183 1184 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { 1185 // We have stored the full entry, but it changed and the server is 1186 // sending a range. We have to delete the old entry. 1187 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1188 DoneWritingToEntry(false); 1189 } 1190 1191 if (mode_ == WRITE && 1192 transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) { 1193 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED); 1194 } 1195 1196 if (mode_ == WRITE && 1197 (request_->method == "PUT" || request_->method == "DELETE")) { 1198 if (NonErrorResponse(new_response->headers->response_code())) { 1199 int ret = cache_->DoomEntry(cache_key_, NULL); 1200 DCHECK_EQ(OK, ret); 1201 } 1202 cache_->DoneWritingToEntry(entry_, true); 1203 entry_ = NULL; 1204 mode_ = NONE; 1205 } 1206 1207 if (request_->method == "POST" && 1208 NonErrorResponse(new_response->headers->response_code())) { 1209 cache_->DoomMainEntryForUrl(request_->url); 1210 } 1211 1212 RecordVaryHeaderHistogram(new_response); 1213 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1214 1215 if (new_response_->headers->response_code() == 416 && 1216 (request_->method == "GET" || request_->method == "POST")) { 1217 // If there is an active entry it may be destroyed with this transaction. 1218 response_ = *new_response_; 1219 return OK; 1220 } 1221 1222 // Are we expecting a response to a conditional query? 1223 if (mode_ == READ_WRITE || mode_ == UPDATE) { 1224 if (new_response->headers->response_code() == 304 || handling_206_) { 1225 UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED); 1226 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 1227 return OK; 1228 } 1229 UpdateTransactionPattern(PATTERN_ENTRY_UPDATED); 1230 mode_ = WRITE; 1231 } 1232 1233 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 1234 return OK; 1235 } 1236 1237 int HttpCache::Transaction::DoNetworkRead() { 1238 next_state_ = STATE_NETWORK_READ_COMPLETE; 1239 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1240 } 1241 1242 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1243 DCHECK(mode_ & WRITE || mode_ == NONE); 1244 1245 if (!cache_.get()) 1246 return ERR_UNEXPECTED; 1247 1248 // If there is an error or we aren't saving the data, we are done; just wait 1249 // until the destructor runs to see if we can keep the data. 1250 if (mode_ == NONE || result < 0) 1251 return result; 1252 1253 next_state_ = STATE_CACHE_WRITE_DATA; 1254 return result; 1255 } 1256 1257 int HttpCache::Transaction::DoInitEntry() { 1258 DCHECK(!new_entry_); 1259 1260 if (!cache_.get()) 1261 return ERR_UNEXPECTED; 1262 1263 if (mode_ == WRITE) { 1264 next_state_ = STATE_DOOM_ENTRY; 1265 return OK; 1266 } 1267 1268 next_state_ = STATE_OPEN_ENTRY; 1269 return OK; 1270 } 1271 1272 int HttpCache::Transaction::DoOpenEntry() { 1273 DCHECK(!new_entry_); 1274 next_state_ = STATE_OPEN_ENTRY_COMPLETE; 1275 cache_pending_ = true; 1276 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY); 1277 first_cache_access_since_ = TimeTicks::Now(); 1278 return cache_->OpenEntry(cache_key_, &new_entry_, this); 1279 } 1280 1281 int HttpCache::Transaction::DoOpenEntryComplete(int result) { 1282 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 1283 // OK, otherwise the cache will end up with an active entry without any 1284 // transaction attached. 1285 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); 1286 cache_pending_ = false; 1287 if (result == OK) { 1288 next_state_ = STATE_ADD_TO_ENTRY; 1289 return OK; 1290 } 1291 1292 if (result == ERR_CACHE_RACE) { 1293 next_state_ = STATE_INIT_ENTRY; 1294 return OK; 1295 } 1296 1297 if (request_->method == "PUT" || request_->method == "DELETE" || 1298 (request_->method == "HEAD" && mode_ == READ_WRITE)) { 1299 DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD"); 1300 mode_ = NONE; 1301 next_state_ = STATE_SEND_REQUEST; 1302 return OK; 1303 } 1304 1305 if (mode_ == READ_WRITE) { 1306 mode_ = WRITE; 1307 next_state_ = STATE_CREATE_ENTRY; 1308 return OK; 1309 } 1310 if (mode_ == UPDATE) { 1311 // There is no cache entry to update; proceed without caching. 1312 mode_ = NONE; 1313 next_state_ = STATE_SEND_REQUEST; 1314 return OK; 1315 } 1316 if (cache_->mode() == PLAYBACK) 1317 DVLOG(1) << "Playback Cache Miss: " << request_->url; 1318 1319 // The entry does not exist, and we are not permitted to create a new entry, 1320 // so we must fail. 1321 return ERR_CACHE_MISS; 1322 } 1323 1324 int HttpCache::Transaction::DoCreateEntry() { 1325 DCHECK(!new_entry_); 1326 next_state_ = STATE_CREATE_ENTRY_COMPLETE; 1327 cache_pending_ = true; 1328 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY); 1329 return cache_->CreateEntry(cache_key_, &new_entry_, this); 1330 } 1331 1332 int HttpCache::Transaction::DoCreateEntryComplete(int result) { 1333 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 1334 // OK, otherwise the cache will end up with an active entry without any 1335 // transaction attached. 1336 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, 1337 result); 1338 cache_pending_ = false; 1339 next_state_ = STATE_ADD_TO_ENTRY; 1340 1341 if (result == ERR_CACHE_RACE) { 1342 next_state_ = STATE_INIT_ENTRY; 1343 return OK; 1344 } 1345 1346 if (result == OK) { 1347 UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", false); 1348 } else { 1349 UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", true); 1350 // We have a race here: Maybe we failed to open the entry and decided to 1351 // create one, but by the time we called create, another transaction already 1352 // created the entry. If we want to eliminate this issue, we need an atomic 1353 // OpenOrCreate() method exposed by the disk cache. 1354 DLOG(WARNING) << "Unable to create cache entry"; 1355 mode_ = NONE; 1356 if (partial_.get()) 1357 partial_->RestoreHeaders(&custom_request_->extra_headers); 1358 next_state_ = STATE_SEND_REQUEST; 1359 } 1360 return OK; 1361 } 1362 1363 int HttpCache::Transaction::DoDoomEntry() { 1364 next_state_ = STATE_DOOM_ENTRY_COMPLETE; 1365 cache_pending_ = true; 1366 if (first_cache_access_since_.is_null()) 1367 first_cache_access_since_ = TimeTicks::Now(); 1368 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY); 1369 return cache_->DoomEntry(cache_key_, this); 1370 } 1371 1372 int HttpCache::Transaction::DoDoomEntryComplete(int result) { 1373 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); 1374 next_state_ = STATE_CREATE_ENTRY; 1375 cache_pending_ = false; 1376 if (result == ERR_CACHE_RACE) 1377 next_state_ = STATE_INIT_ENTRY; 1378 return OK; 1379 } 1380 1381 int HttpCache::Transaction::DoAddToEntry() { 1382 DCHECK(new_entry_); 1383 cache_pending_ = true; 1384 next_state_ = STATE_ADD_TO_ENTRY_COMPLETE; 1385 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY); 1386 DCHECK(entry_lock_waiting_since_.is_null()); 1387 entry_lock_waiting_since_ = TimeTicks::Now(); 1388 int rv = cache_->AddTransactionToEntry(new_entry_, this); 1389 if (rv == ERR_IO_PENDING) { 1390 if (bypass_lock_for_test_) { 1391 OnAddToEntryTimeout(entry_lock_waiting_since_); 1392 } else { 1393 int timeout_milliseconds = 20 * 1000; 1394 if (partial_ && new_entry_->writer && 1395 new_entry_->writer->range_requested_) { 1396 // Quickly timeout and bypass the cache if we're a range request and 1397 // we're blocked by the reader/writer lock. Doing so eliminates a long 1398 // running issue, http://crbug.com/31014, where two of the same media 1399 // resources could not be played back simultaneously due to one locking 1400 // the cache entry until the entire video was downloaded. 1401 // 1402 // Bypassing the cache is not ideal, as we are now ignoring the cache 1403 // entirely for all range requests to a resource beyond the first. This 1404 // is however a much more succinct solution than the alternatives, which 1405 // would require somewhat significant changes to the http caching logic. 1406 // 1407 // Allow some timeout slack for the entry addition to complete in case 1408 // the writer lock is imminently released; we want to avoid skipping 1409 // the cache if at all possible. See http://crbug.com/408765 1410 timeout_milliseconds = 25; 1411 } 1412 base::MessageLoop::current()->PostDelayedTask( 1413 FROM_HERE, 1414 base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout, 1415 weak_factory_.GetWeakPtr(), entry_lock_waiting_since_), 1416 TimeDelta::FromMilliseconds(timeout_milliseconds)); 1417 } 1418 } 1419 return rv; 1420 } 1421 1422 int HttpCache::Transaction::DoAddToEntryComplete(int result) { 1423 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY, 1424 result); 1425 const TimeDelta entry_lock_wait = 1426 TimeTicks::Now() - entry_lock_waiting_since_; 1427 UMA_HISTOGRAM_TIMES("HttpCache.EntryLockWait", entry_lock_wait); 1428 1429 entry_lock_waiting_since_ = TimeTicks(); 1430 DCHECK(new_entry_); 1431 cache_pending_ = false; 1432 1433 if (result == OK) 1434 entry_ = new_entry_; 1435 1436 // If there is a failure, the cache should have taken care of new_entry_. 1437 new_entry_ = NULL; 1438 1439 if (result == ERR_CACHE_RACE) { 1440 next_state_ = STATE_INIT_ENTRY; 1441 return OK; 1442 } 1443 1444 if (result == ERR_CACHE_LOCK_TIMEOUT) { 1445 // The cache is busy, bypass it for this transaction. 1446 mode_ = NONE; 1447 next_state_ = STATE_SEND_REQUEST; 1448 if (partial_) { 1449 partial_->RestoreHeaders(&custom_request_->extra_headers); 1450 partial_.reset(); 1451 } 1452 return OK; 1453 } 1454 1455 if (result != OK) { 1456 NOTREACHED(); 1457 return result; 1458 } 1459 1460 if (mode_ == WRITE) { 1461 if (partial_.get()) 1462 partial_->RestoreHeaders(&custom_request_->extra_headers); 1463 next_state_ = STATE_SEND_REQUEST; 1464 } else { 1465 // We have to read the headers from the cached entry. 1466 DCHECK(mode_ & READ_META); 1467 next_state_ = STATE_CACHE_READ_RESPONSE; 1468 } 1469 return OK; 1470 } 1471 1472 // We may end up here multiple times for a given request. 1473 int HttpCache::Transaction::DoStartPartialCacheValidation() { 1474 if (mode_ == NONE) 1475 return OK; 1476 1477 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION; 1478 return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_); 1479 } 1480 1481 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { 1482 if (!result) { 1483 // This is the end of the request. 1484 if (mode_ & WRITE) { 1485 DoneWritingToEntry(true); 1486 } else { 1487 cache_->DoneReadingFromEntry(entry_, this); 1488 entry_ = NULL; 1489 } 1490 return result; 1491 } 1492 1493 if (result < 0) 1494 return result; 1495 1496 partial_->PrepareCacheValidation(entry_->disk_entry, 1497 &custom_request_->extra_headers); 1498 1499 if (reading_ && partial_->IsCurrentRangeCached()) { 1500 next_state_ = STATE_CACHE_READ_DATA; 1501 return OK; 1502 } 1503 1504 return BeginCacheValidation(); 1505 } 1506 1507 // We received 304 or 206 and we want to update the cached response headers. 1508 int HttpCache::Transaction::DoUpdateCachedResponse() { 1509 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1510 int rv = OK; 1511 // Update cached response based on headers in new_response. 1512 // TODO(wtc): should we update cached certificate (response_.ssl_info), too? 1513 response_.headers->Update(*new_response_->headers.get()); 1514 response_.response_time = new_response_->response_time; 1515 response_.request_time = new_response_->request_time; 1516 response_.network_accessed = new_response_->network_accessed; 1517 1518 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { 1519 if (!entry_->doomed) { 1520 int ret = cache_->DoomEntry(cache_key_, NULL); 1521 DCHECK_EQ(OK, ret); 1522 } 1523 } else { 1524 // If we are already reading, we already updated the headers for this 1525 // request; doing it again will change Content-Length. 1526 if (!reading_) { 1527 target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1528 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1529 rv = OK; 1530 } 1531 } 1532 return rv; 1533 } 1534 1535 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { 1536 if (mode_ == UPDATE) { 1537 DCHECK(!handling_206_); 1538 // We got a "not modified" response and already updated the corresponding 1539 // cache entry above. 1540 // 1541 // By closing the cached entry now, we make sure that the 304 rather than 1542 // the cached 200 response, is what will be returned to the user. 1543 DoneWritingToEntry(true); 1544 } else if (entry_ && !handling_206_) { 1545 DCHECK_EQ(READ_WRITE, mode_); 1546 if (!partial_.get() || partial_->IsLastRange()) { 1547 cache_->ConvertWriterToReader(entry_); 1548 mode_ = READ; 1549 } 1550 // We no longer need the network transaction, so destroy it. 1551 final_upload_progress_ = network_trans_->GetUploadProgress(); 1552 ResetNetworkTransaction(); 1553 } else if (entry_ && handling_206_ && truncated_ && 1554 partial_->initial_validation()) { 1555 // We just finished the validation of a truncated entry, and the server 1556 // is willing to resume the operation. Now we go back and start serving 1557 // the first part to the user. 1558 ResetNetworkTransaction(); 1559 new_response_ = NULL; 1560 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1561 partial_->SetRangeToStartDownload(); 1562 return OK; 1563 } 1564 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 1565 return OK; 1566 } 1567 1568 int HttpCache::Transaction::DoOverwriteCachedResponse() { 1569 if (mode_ & READ) { 1570 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1571 return OK; 1572 } 1573 1574 // We change the value of Content-Length for partial content. 1575 if (handling_206_ && partial_.get()) 1576 partial_->FixContentLength(new_response_->headers.get()); 1577 1578 response_ = *new_response_; 1579 1580 if (request_->method == "HEAD") { 1581 // This response is replacing the cached one. 1582 DoneWritingToEntry(false); 1583 mode_ = NONE; 1584 new_response_ = NULL; 1585 return OK; 1586 } 1587 1588 target_state_ = STATE_TRUNCATE_CACHED_DATA; 1589 next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE : 1590 STATE_CACHE_WRITE_RESPONSE; 1591 return OK; 1592 } 1593 1594 int HttpCache::Transaction::DoTruncateCachedData() { 1595 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1596 if (!entry_) 1597 return OK; 1598 if (net_log_.IsLogging()) 1599 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); 1600 // Truncate the stream. 1601 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_); 1602 } 1603 1604 int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) { 1605 if (entry_) { 1606 if (net_log_.IsLogging()) { 1607 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1608 result); 1609 } 1610 } 1611 1612 next_state_ = STATE_TRUNCATE_CACHED_METADATA; 1613 return OK; 1614 } 1615 1616 int HttpCache::Transaction::DoTruncateCachedMetadata() { 1617 next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE; 1618 if (!entry_) 1619 return OK; 1620 1621 if (net_log_.IsLogging()) 1622 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 1623 return WriteToEntry(kMetadataIndex, 0, NULL, 0, io_callback_); 1624 } 1625 1626 int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) { 1627 if (entry_) { 1628 if (net_log_.IsLogging()) { 1629 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 1630 result); 1631 } 1632 } 1633 1634 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1635 return OK; 1636 } 1637 1638 int HttpCache::Transaction::DoPartialHeadersReceived() { 1639 new_response_ = NULL; 1640 if (entry_ && !partial_.get() && 1641 entry_->disk_entry->GetDataSize(kMetadataIndex)) 1642 next_state_ = STATE_CACHE_READ_METADATA; 1643 1644 if (!partial_.get()) 1645 return OK; 1646 1647 if (reading_) { 1648 if (network_trans_.get()) { 1649 next_state_ = STATE_NETWORK_READ; 1650 } else { 1651 next_state_ = STATE_CACHE_READ_DATA; 1652 } 1653 } else if (mode_ != NONE) { 1654 // We are about to return the headers for a byte-range request to the user, 1655 // so let's fix them. 1656 partial_->FixResponseHeaders(response_.headers.get(), true); 1657 } 1658 return OK; 1659 } 1660 1661 int HttpCache::Transaction::DoCacheReadResponse() { 1662 DCHECK(entry_); 1663 next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE; 1664 1665 io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex); 1666 read_buf_ = new IOBuffer(io_buf_len_); 1667 1668 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); 1669 return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(), 1670 io_buf_len_, io_callback_); 1671 } 1672 1673 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { 1674 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1675 if (result != io_buf_len_ || 1676 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, 1677 &response_, &truncated_)) { 1678 return OnCacheReadError(result, true); 1679 } 1680 1681 // cert_cache() will be null if the CertCacheTrial field trial is disabled. 1682 if (cache_->cert_cache() && response_.ssl_info.is_valid()) 1683 ReadCertChain(); 1684 1685 // Some resources may have slipped in as truncated when they're not. 1686 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1687 if (response_.headers->GetContentLength() == current_size) 1688 truncated_ = false; 1689 1690 // We now have access to the cache entry. 1691 // 1692 // o if we are a reader for the transaction, then we can start reading the 1693 // cache entry. 1694 // 1695 // o if we can read or write, then we should check if the cache entry needs 1696 // to be validated and then issue a network request if needed or just read 1697 // from the cache if the cache entry is already valid. 1698 // 1699 // o if we are set to UPDATE, then we are handling an externally 1700 // conditionalized request (if-modified-since / if-none-match). We check 1701 // if the request headers define a validation request. 1702 // 1703 switch (mode_) { 1704 case READ: 1705 UpdateTransactionPattern(PATTERN_ENTRY_USED); 1706 result = BeginCacheRead(); 1707 break; 1708 case READ_WRITE: 1709 result = BeginPartialCacheValidation(); 1710 break; 1711 case UPDATE: 1712 result = BeginExternallyConditionalizedRequest(); 1713 break; 1714 case WRITE: 1715 default: 1716 NOTREACHED(); 1717 result = ERR_FAILED; 1718 } 1719 return result; 1720 } 1721 1722 int HttpCache::Transaction::DoCacheWriteResponse() { 1723 if (entry_) { 1724 if (net_log_.IsLogging()) 1725 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 1726 } 1727 return WriteResponseInfoToEntry(false); 1728 } 1729 1730 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 1731 if (entry_) { 1732 if (net_log_.IsLogging()) 1733 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 1734 } 1735 return WriteResponseInfoToEntry(true); 1736 } 1737 1738 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1739 next_state_ = target_state_; 1740 target_state_ = STATE_NONE; 1741 if (!entry_) 1742 return OK; 1743 if (net_log_.IsLogging()) { 1744 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 1745 result); 1746 } 1747 1748 // Balance the AddRef from WriteResponseInfoToEntry. 1749 if (result != io_buf_len_) { 1750 DLOG(ERROR) << "failed to write response info to cache"; 1751 DoneWritingToEntry(false); 1752 } 1753 return OK; 1754 } 1755 1756 int HttpCache::Transaction::DoCacheReadMetadata() { 1757 DCHECK(entry_); 1758 DCHECK(!response_.metadata.get()); 1759 next_state_ = STATE_CACHE_READ_METADATA_COMPLETE; 1760 1761 response_.metadata = 1762 new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex)); 1763 1764 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); 1765 return entry_->disk_entry->ReadData(kMetadataIndex, 0, 1766 response_.metadata.get(), 1767 response_.metadata->size(), 1768 io_callback_); 1769 } 1770 1771 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1772 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1773 if (result != response_.metadata->size()) 1774 return OnCacheReadError(result, false); 1775 return OK; 1776 } 1777 1778 int HttpCache::Transaction::DoCacheQueryData() { 1779 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; 1780 return entry_->disk_entry->ReadyForSparseIO(io_callback_); 1781 } 1782 1783 int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { 1784 if (result == ERR_NOT_IMPLEMENTED) { 1785 // Restart the request overwriting the cache entry. 1786 // TODO(pasko): remove this workaround as soon as the SimpleBackendImpl 1787 // supports Sparse IO. 1788 return DoRestartPartialRequest(); 1789 } 1790 DCHECK_EQ(OK, result); 1791 if (!cache_.get()) 1792 return ERR_UNEXPECTED; 1793 1794 return ValidateEntryHeadersAndContinue(); 1795 } 1796 1797 int HttpCache::Transaction::DoCacheReadData() { 1798 DCHECK(entry_); 1799 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 1800 1801 if (net_log_.IsLogging()) 1802 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA); 1803 if (partial_.get()) { 1804 return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_, 1805 io_callback_); 1806 } 1807 1808 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, 1809 read_buf_.get(), io_buf_len_, 1810 io_callback_); 1811 } 1812 1813 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1814 if (net_log_.IsLogging()) { 1815 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1816 result); 1817 } 1818 1819 if (!cache_.get()) 1820 return ERR_UNEXPECTED; 1821 1822 if (partial_.get()) { 1823 // Partial requests are confusing to report in histograms because they may 1824 // have multiple underlying requests. 1825 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1826 return DoPartialCacheReadCompleted(result); 1827 } 1828 1829 if (result > 0) { 1830 read_offset_ += result; 1831 } else if (result == 0) { // End of file. 1832 RecordHistograms(); 1833 cache_->DoneReadingFromEntry(entry_, this); 1834 entry_ = NULL; 1835 } else { 1836 return OnCacheReadError(result, false); 1837 } 1838 return result; 1839 } 1840 1841 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1842 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1843 write_len_ = num_bytes; 1844 if (entry_) { 1845 if (net_log_.IsLogging()) 1846 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); 1847 } 1848 1849 return AppendResponseDataToEntry(read_buf_.get(), num_bytes, io_callback_); 1850 } 1851 1852 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 1853 if (entry_) { 1854 if (net_log_.IsLogging()) { 1855 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1856 result); 1857 } 1858 } 1859 // Balance the AddRef from DoCacheWriteData. 1860 if (!cache_.get()) 1861 return ERR_UNEXPECTED; 1862 1863 if (result != write_len_) { 1864 DLOG(ERROR) << "failed to write response data to cache"; 1865 DoneWritingToEntry(false); 1866 1867 // We want to ignore errors writing to disk and just keep reading from 1868 // the network. 1869 result = write_len_; 1870 } else if (!done_reading_ && entry_) { 1871 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1872 int64 body_size = response_.headers->GetContentLength(); 1873 if (body_size >= 0 && body_size <= current_size) 1874 done_reading_ = true; 1875 } 1876 1877 if (partial_.get()) { 1878 // This may be the last request. 1879 if (!(result == 0 && !truncated_ && 1880 (partial_->IsLastRange() || mode_ == WRITE))) 1881 return DoPartialNetworkReadCompleted(result); 1882 } 1883 1884 if (result == 0) { 1885 // End of file. This may be the result of a connection problem so see if we 1886 // have to keep the entry around to be flagged as truncated later on. 1887 if (done_reading_ || !entry_ || partial_.get() || 1888 response_.headers->GetContentLength() <= 0) 1889 DoneWritingToEntry(true); 1890 } 1891 1892 return result; 1893 } 1894 1895 //----------------------------------------------------------------------------- 1896 1897 void HttpCache::Transaction::ReadCertChain() { 1898 std::string key = 1899 GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle()); 1900 const X509Certificate::OSCertHandles& intermediates = 1901 response_.ssl_info.cert->GetIntermediateCertificates(); 1902 int dist_from_root = intermediates.size(); 1903 1904 scoped_refptr<SharedChainData> shared_chain_data( 1905 new SharedChainData(intermediates.size() + 1, TimeTicks::Now())); 1906 cache_->cert_cache()->GetCertificate(key, 1907 base::Bind(&OnCertReadIOComplete, 1908 dist_from_root, 1909 true /* is leaf */, 1910 shared_chain_data)); 1911 1912 for (X509Certificate::OSCertHandles::const_iterator it = 1913 intermediates.begin(); 1914 it != intermediates.end(); 1915 ++it) { 1916 --dist_from_root; 1917 key = GetCacheKeyForCert(*it); 1918 cache_->cert_cache()->GetCertificate(key, 1919 base::Bind(&OnCertReadIOComplete, 1920 dist_from_root, 1921 false /* is not leaf */, 1922 shared_chain_data)); 1923 } 1924 DCHECK_EQ(0, dist_from_root); 1925 } 1926 1927 void HttpCache::Transaction::WriteCertChain() { 1928 const X509Certificate::OSCertHandles& intermediates = 1929 response_.ssl_info.cert->GetIntermediateCertificates(); 1930 int dist_from_root = intermediates.size(); 1931 1932 scoped_refptr<SharedChainData> shared_chain_data( 1933 new SharedChainData(intermediates.size() + 1, TimeTicks::Now())); 1934 cache_->cert_cache()->SetCertificate( 1935 response_.ssl_info.cert->os_cert_handle(), 1936 base::Bind(&OnCertWriteIOComplete, 1937 dist_from_root, 1938 true /* is leaf */, 1939 shared_chain_data)); 1940 for (X509Certificate::OSCertHandles::const_iterator it = 1941 intermediates.begin(); 1942 it != intermediates.end(); 1943 ++it) { 1944 --dist_from_root; 1945 cache_->cert_cache()->SetCertificate(*it, 1946 base::Bind(&OnCertWriteIOComplete, 1947 dist_from_root, 1948 false /* is not leaf */, 1949 shared_chain_data)); 1950 } 1951 DCHECK_EQ(0, dist_from_root); 1952 } 1953 1954 void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log, 1955 const HttpRequestInfo* request) { 1956 net_log_ = net_log; 1957 request_ = request; 1958 effective_load_flags_ = request_->load_flags; 1959 1960 switch (cache_->mode()) { 1961 case NORMAL: 1962 break; 1963 case RECORD: 1964 // When in record mode, we want to NEVER load from the cache. 1965 // The reason for this is because we save the Set-Cookie headers 1966 // (intentionally). If we read from the cache, we replay them 1967 // prematurely. 1968 effective_load_flags_ |= LOAD_BYPASS_CACHE; 1969 break; 1970 case PLAYBACK: 1971 // When in playback mode, we want to load exclusively from the cache. 1972 effective_load_flags_ |= LOAD_ONLY_FROM_CACHE; 1973 break; 1974 case DISABLE: 1975 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1976 break; 1977 } 1978 1979 // Some headers imply load flags. The order here is significant. 1980 // 1981 // LOAD_DISABLE_CACHE : no cache read or write 1982 // LOAD_BYPASS_CACHE : no cache read 1983 // LOAD_VALIDATE_CACHE : no cache read unless validation 1984 // 1985 // The former modes trump latter modes, so if we find a matching header we 1986 // can stop iterating kSpecialHeaders. 1987 // 1988 static const struct { 1989 const HeaderNameAndValue* search; 1990 int load_flag; 1991 } kSpecialHeaders[] = { 1992 { kPassThroughHeaders, LOAD_DISABLE_CACHE }, 1993 { kForceFetchHeaders, LOAD_BYPASS_CACHE }, 1994 { kForceValidateHeaders, LOAD_VALIDATE_CACHE }, 1995 }; 1996 1997 bool range_found = false; 1998 bool external_validation_error = false; 1999 2000 if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange)) 2001 range_found = true; 2002 2003 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) { 2004 if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) { 2005 effective_load_flags_ |= kSpecialHeaders[i].load_flag; 2006 break; 2007 } 2008 } 2009 2010 // Check for conditionalization headers which may correspond with a 2011 // cache validation request. 2012 for (size_t i = 0; i < arraysize(kValidationHeaders); ++i) { 2013 const ValidationHeaderInfo& info = kValidationHeaders[i]; 2014 std::string validation_value; 2015 if (request_->extra_headers.GetHeader( 2016 info.request_header_name, &validation_value)) { 2017 if (!external_validation_.values[i].empty() || 2018 validation_value.empty()) { 2019 external_validation_error = true; 2020 } 2021 external_validation_.values[i] = validation_value; 2022 external_validation_.initialized = true; 2023 } 2024 } 2025 2026 // We don't support ranges and validation headers. 2027 if (range_found && external_validation_.initialized) { 2028 LOG(WARNING) << "Byte ranges AND validation headers found."; 2029 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2030 } 2031 2032 // If there is more than one validation header, we can't treat this request as 2033 // a cache validation, since we don't know for sure which header the server 2034 // will give us a response for (and they could be contradictory). 2035 if (external_validation_error) { 2036 LOG(WARNING) << "Multiple or malformed validation headers found."; 2037 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2038 } 2039 2040 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { 2041 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2042 partial_.reset(new PartialData); 2043 if (request_->method == "GET" && partial_->Init(request_->extra_headers)) { 2044 // We will be modifying the actual range requested to the server, so 2045 // let's remove the header here. 2046 custom_request_.reset(new HttpRequestInfo(*request_)); 2047 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange); 2048 request_ = custom_request_.get(); 2049 partial_->SetHeaders(custom_request_->extra_headers); 2050 } else { 2051 // The range is invalid or we cannot handle it properly. 2052 VLOG(1) << "Invalid byte range found."; 2053 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2054 partial_.reset(NULL); 2055 } 2056 } 2057 } 2058 2059 bool HttpCache::Transaction::ShouldPassThrough() { 2060 // We may have a null disk_cache if there is an error we cannot recover from, 2061 // like not enough disk space, or sharing violations. 2062 if (!cache_->disk_cache_.get()) 2063 return true; 2064 2065 // When using the record/playback modes, we always use the cache 2066 // and we never pass through. 2067 if (cache_->mode() == RECORD || cache_->mode() == PLAYBACK) 2068 return false; 2069 2070 if (effective_load_flags_ & LOAD_DISABLE_CACHE) 2071 return true; 2072 2073 if (request_->method == "GET" || request_->method == "HEAD") 2074 return false; 2075 2076 if (request_->method == "POST" && request_->upload_data_stream && 2077 request_->upload_data_stream->identifier()) { 2078 return false; 2079 } 2080 2081 if (request_->method == "PUT" && request_->upload_data_stream) 2082 return false; 2083 2084 if (request_->method == "DELETE") 2085 return false; 2086 2087 return true; 2088 } 2089 2090 int HttpCache::Transaction::BeginCacheRead() { 2091 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. 2092 if (response_.headers->response_code() == 206 || partial_.get()) { 2093 NOTREACHED(); 2094 return ERR_CACHE_MISS; 2095 } 2096 2097 if (request_->method == "HEAD") 2098 FixHeadersForHead(); 2099 2100 // We don't have the whole resource. 2101 if (truncated_) 2102 return ERR_CACHE_MISS; 2103 2104 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) 2105 next_state_ = STATE_CACHE_READ_METADATA; 2106 2107 return OK; 2108 } 2109 2110 int HttpCache::Transaction::BeginCacheValidation() { 2111 DCHECK(mode_ == READ_WRITE); 2112 2113 bool skip_validation = !RequiresValidation(); 2114 2115 if (request_->method == "HEAD" && 2116 (truncated_ || response_.headers->response_code() == 206)) { 2117 DCHECK(!partial_); 2118 if (skip_validation) 2119 return SetupEntryForRead(); 2120 2121 // Bail out! 2122 next_state_ = STATE_SEND_REQUEST; 2123 mode_ = NONE; 2124 return OK; 2125 } 2126 2127 if (truncated_) { 2128 // Truncated entries can cause partial gets, so we shouldn't record this 2129 // load in histograms. 2130 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2131 skip_validation = !partial_->initial_validation(); 2132 } 2133 2134 if (partial_.get() && (is_sparse_ || truncated_) && 2135 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 2136 // Force revalidation for sparse or truncated entries. Note that we don't 2137 // want to ignore the regular validation logic just because a byte range was 2138 // part of the request. 2139 skip_validation = false; 2140 } 2141 2142 if (skip_validation) { 2143 UpdateTransactionPattern(PATTERN_ENTRY_USED); 2144 RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE); 2145 return SetupEntryForRead(); 2146 } else { 2147 // Make the network request conditional, to see if we may reuse our cached 2148 // response. If we cannot do so, then we just resort to a normal fetch. 2149 // Our mode remains READ_WRITE for a conditional request. Even if the 2150 // conditionalization fails, we don't switch to WRITE mode until we 2151 // know we won't be falling back to using the cache entry in the 2152 // LOAD_FROM_CACHE_IF_OFFLINE case. 2153 if (!ConditionalizeRequest()) { 2154 couldnt_conditionalize_request_ = true; 2155 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); 2156 if (partial_.get()) 2157 return DoRestartPartialRequest(); 2158 2159 DCHECK_NE(206, response_.headers->response_code()); 2160 } 2161 next_state_ = STATE_SEND_REQUEST; 2162 } 2163 return OK; 2164 } 2165 2166 int HttpCache::Transaction::BeginPartialCacheValidation() { 2167 DCHECK(mode_ == READ_WRITE); 2168 2169 if (response_.headers->response_code() != 206 && !partial_.get() && 2170 !truncated_) { 2171 return BeginCacheValidation(); 2172 } 2173 2174 // Partial requests should not be recorded in histograms. 2175 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2176 if (range_requested_) { 2177 next_state_ = STATE_CACHE_QUERY_DATA; 2178 return OK; 2179 } 2180 2181 // The request is not for a range, but we have stored just ranges. 2182 2183 if (request_->method == "HEAD") 2184 return BeginCacheValidation(); 2185 2186 partial_.reset(new PartialData()); 2187 partial_->SetHeaders(request_->extra_headers); 2188 if (!custom_request_.get()) { 2189 custom_request_.reset(new HttpRequestInfo(*request_)); 2190 request_ = custom_request_.get(); 2191 } 2192 2193 return ValidateEntryHeadersAndContinue(); 2194 } 2195 2196 // This should only be called once per request. 2197 int HttpCache::Transaction::ValidateEntryHeadersAndContinue() { 2198 DCHECK(mode_ == READ_WRITE); 2199 2200 if (!partial_->UpdateFromStoredHeaders( 2201 response_.headers.get(), entry_->disk_entry, truncated_)) { 2202 return DoRestartPartialRequest(); 2203 } 2204 2205 if (response_.headers->response_code() == 206) 2206 is_sparse_ = true; 2207 2208 if (!partial_->IsRequestedRangeOK()) { 2209 // The stored data is fine, but the request may be invalid. 2210 invalid_range_ = true; 2211 } 2212 2213 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 2214 return OK; 2215 } 2216 2217 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { 2218 DCHECK_EQ(UPDATE, mode_); 2219 DCHECK(external_validation_.initialized); 2220 2221 for (size_t i = 0; i < arraysize(kValidationHeaders); i++) { 2222 if (external_validation_.values[i].empty()) 2223 continue; 2224 // Retrieve either the cached response's "etag" or "last-modified" header. 2225 std::string validator; 2226 response_.headers->EnumerateHeader( 2227 NULL, 2228 kValidationHeaders[i].related_response_header_name, 2229 &validator); 2230 2231 if (response_.headers->response_code() != 200 || truncated_ || 2232 validator.empty() || validator != external_validation_.values[i]) { 2233 // The externally conditionalized request is not a validation request 2234 // for our existing cache entry. Proceed with caching disabled. 2235 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2236 DoneWritingToEntry(true); 2237 } 2238 } 2239 2240 // TODO(ricea): This calculation is expensive to perform just to collect 2241 // statistics. Either remove it or use the result, depending on the result of 2242 // the experiment. 2243 ExternallyConditionalizedType type = 2244 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE; 2245 if (mode_ == NONE) 2246 type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS; 2247 else if (RequiresValidation()) 2248 type = EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION; 2249 2250 // TODO(ricea): Add CACHE_USABLE_STALE once stale-while-revalidate CL landed. 2251 // TODO(ricea): Either remove this histogram or make it permanent by M40. 2252 UMA_HISTOGRAM_ENUMERATION("HttpCache.ExternallyConditionalized", 2253 type, 2254 EXTERNALLY_CONDITIONALIZED_MAX); 2255 2256 next_state_ = STATE_SEND_REQUEST; 2257 return OK; 2258 } 2259 2260 int HttpCache::Transaction::RestartNetworkRequest() { 2261 DCHECK(mode_ & WRITE || mode_ == NONE); 2262 DCHECK(network_trans_.get()); 2263 DCHECK_EQ(STATE_NONE, next_state_); 2264 2265 next_state_ = STATE_SEND_REQUEST_COMPLETE; 2266 int rv = network_trans_->RestartIgnoringLastError(io_callback_); 2267 if (rv != ERR_IO_PENDING) 2268 return DoLoop(rv); 2269 return rv; 2270 } 2271 2272 int HttpCache::Transaction::RestartNetworkRequestWithCertificate( 2273 X509Certificate* client_cert) { 2274 DCHECK(mode_ & WRITE || mode_ == NONE); 2275 DCHECK(network_trans_.get()); 2276 DCHECK_EQ(STATE_NONE, next_state_); 2277 2278 next_state_ = STATE_SEND_REQUEST_COMPLETE; 2279 int rv = network_trans_->RestartWithCertificate(client_cert, io_callback_); 2280 if (rv != ERR_IO_PENDING) 2281 return DoLoop(rv); 2282 return rv; 2283 } 2284 2285 int HttpCache::Transaction::RestartNetworkRequestWithAuth( 2286 const AuthCredentials& credentials) { 2287 DCHECK(mode_ & WRITE || mode_ == NONE); 2288 DCHECK(network_trans_.get()); 2289 DCHECK_EQ(STATE_NONE, next_state_); 2290 2291 next_state_ = STATE_SEND_REQUEST_COMPLETE; 2292 int rv = network_trans_->RestartWithAuth(credentials, io_callback_); 2293 if (rv != ERR_IO_PENDING) 2294 return DoLoop(rv); 2295 return rv; 2296 } 2297 2298 bool HttpCache::Transaction::RequiresValidation() { 2299 // TODO(darin): need to do more work here: 2300 // - make sure we have a matching request method 2301 // - watch out for cached responses that depend on authentication 2302 2303 // In playback mode, nothing requires validation. 2304 if (cache_->mode() == net::HttpCache::PLAYBACK) 2305 return false; 2306 2307 if (response_.vary_data.is_valid() && 2308 !response_.vary_data.MatchesRequest(*request_, 2309 *response_.headers.get())) { 2310 vary_mismatch_ = true; 2311 return true; 2312 } 2313 2314 if (effective_load_flags_ & LOAD_PREFERRING_CACHE) 2315 return false; 2316 2317 if (effective_load_flags_ & LOAD_VALIDATE_CACHE) 2318 return true; 2319 2320 if (request_->method == "PUT" || request_->method == "DELETE") 2321 return true; 2322 2323 if (response_.headers->RequiresValidation( 2324 response_.request_time, response_.response_time, Time::Now())) { 2325 return true; 2326 } 2327 2328 return false; 2329 } 2330 2331 bool HttpCache::Transaction::ConditionalizeRequest() { 2332 DCHECK(response_.headers.get()); 2333 2334 if (request_->method == "PUT" || request_->method == "DELETE") 2335 return false; 2336 2337 // This only makes sense for cached 200 or 206 responses. 2338 if (response_.headers->response_code() != 200 && 2339 response_.headers->response_code() != 206) { 2340 return false; 2341 } 2342 2343 if (response_.headers->response_code() == 206 && 2344 !response_.headers->HasStrongValidators()) { 2345 return false; 2346 } 2347 2348 // Just use the first available ETag and/or Last-Modified header value. 2349 // TODO(darin): Or should we use the last? 2350 2351 std::string etag_value; 2352 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) 2353 response_.headers->EnumerateHeader(NULL, "etag", &etag_value); 2354 2355 std::string last_modified_value; 2356 if (!vary_mismatch_) { 2357 response_.headers->EnumerateHeader(NULL, "last-modified", 2358 &last_modified_value); 2359 } 2360 2361 if (etag_value.empty() && last_modified_value.empty()) 2362 return false; 2363 2364 if (!partial_.get()) { 2365 // Need to customize the request, so this forces us to allocate :( 2366 custom_request_.reset(new HttpRequestInfo(*request_)); 2367 request_ = custom_request_.get(); 2368 } 2369 DCHECK(custom_request_.get()); 2370 2371 bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() && 2372 !invalid_range_; 2373 2374 if (!use_if_range) { 2375 // stale-while-revalidate is not useful when we only have a partial response 2376 // cached, so don't set the header in that case. 2377 TimeDelta stale_while_revalidate; 2378 if (response_.headers->GetStaleWhileRevalidateValue( 2379 &stale_while_revalidate) && 2380 stale_while_revalidate > TimeDelta()) { 2381 TimeDelta max_age = 2382 response_.headers->GetFreshnessLifetime(response_.response_time); 2383 TimeDelta current_age = response_.headers->GetCurrentAge( 2384 response_.request_time, response_.response_time, Time::Now()); 2385 2386 custom_request_->extra_headers.SetHeader( 2387 kFreshnessHeader, 2388 base::StringPrintf("max-age=%" PRId64 2389 ",stale-while-revalidate=%" PRId64 ",age=%" PRId64, 2390 max_age.InSeconds(), 2391 stale_while_revalidate.InSeconds(), 2392 current_age.InSeconds())); 2393 } 2394 } 2395 2396 if (!etag_value.empty()) { 2397 if (use_if_range) { 2398 // We don't want to switch to WRITE mode if we don't have this block of a 2399 // byte-range request because we may have other parts cached. 2400 custom_request_->extra_headers.SetHeader( 2401 HttpRequestHeaders::kIfRange, etag_value); 2402 } else { 2403 custom_request_->extra_headers.SetHeader( 2404 HttpRequestHeaders::kIfNoneMatch, etag_value); 2405 } 2406 // For byte-range requests, make sure that we use only one way to validate 2407 // the request. 2408 if (partial_.get() && !partial_->IsCurrentRangeCached()) 2409 return true; 2410 } 2411 2412 if (!last_modified_value.empty()) { 2413 if (use_if_range) { 2414 custom_request_->extra_headers.SetHeader( 2415 HttpRequestHeaders::kIfRange, last_modified_value); 2416 } else { 2417 custom_request_->extra_headers.SetHeader( 2418 HttpRequestHeaders::kIfModifiedSince, last_modified_value); 2419 } 2420 } 2421 2422 return true; 2423 } 2424 2425 // We just received some headers from the server. We may have asked for a range, 2426 // in which case partial_ has an object. This could be the first network request 2427 // we make to fulfill the original request, or we may be already reading (from 2428 // the net and / or the cache). If we are not expecting a certain response, we 2429 // just bypass the cache for this request (but again, maybe we are reading), and 2430 // delete partial_ (so we are not able to "fix" the headers that we return to 2431 // the user). This results in either a weird response for the caller (we don't 2432 // expect it after all), or maybe a range that was not exactly what it was asked 2433 // for. 2434 // 2435 // If the server is simply telling us that the resource has changed, we delete 2436 // the cached entry and restart the request as the caller intended (by returning 2437 // false from this method). However, we may not be able to do that at any point, 2438 // for instance if we already returned the headers to the user. 2439 // 2440 // WARNING: Whenever this code returns false, it has to make sure that the next 2441 // time it is called it will return true so that we don't keep retrying the 2442 // request. 2443 bool HttpCache::Transaction::ValidatePartialResponse() { 2444 const HttpResponseHeaders* headers = new_response_->headers.get(); 2445 int response_code = headers->response_code(); 2446 bool partial_response = (response_code == 206); 2447 handling_206_ = false; 2448 2449 if (!entry_ || request_->method != "GET") 2450 return true; 2451 2452 if (invalid_range_) { 2453 // We gave up trying to match this request with the stored data. If the 2454 // server is ok with the request, delete the entry, otherwise just ignore 2455 // this request 2456 DCHECK(!reading_); 2457 if (partial_response || response_code == 200) { 2458 DoomPartialEntry(true); 2459 mode_ = NONE; 2460 } else { 2461 if (response_code == 304) 2462 FailRangeRequest(); 2463 IgnoreRangeRequest(); 2464 } 2465 return true; 2466 } 2467 2468 if (!partial_.get()) { 2469 // We are not expecting 206 but we may have one. 2470 if (partial_response) 2471 IgnoreRangeRequest(); 2472 2473 return true; 2474 } 2475 2476 // TODO(rvargas): Do we need to consider other results here?. 2477 bool failure = response_code == 200 || response_code == 416; 2478 2479 if (partial_->IsCurrentRangeCached()) { 2480 // We asked for "If-None-Match: " so a 206 means a new object. 2481 if (partial_response) 2482 failure = true; 2483 2484 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) 2485 return true; 2486 } else { 2487 // We asked for "If-Range: " so a 206 means just another range. 2488 if (partial_response && partial_->ResponseHeadersOK(headers)) { 2489 handling_206_ = true; 2490 return true; 2491 } 2492 2493 if (!reading_ && !is_sparse_ && !partial_response) { 2494 // See if we can ignore the fact that we issued a byte range request. 2495 // If the server sends 200, just store it. If it sends an error, redirect 2496 // or something else, we may store the response as long as we didn't have 2497 // anything already stored. 2498 if (response_code == 200 || 2499 (!truncated_ && response_code != 304 && response_code != 416)) { 2500 // The server is sending something else, and we can save it. 2501 DCHECK((truncated_ && !partial_->IsLastRange()) || range_requested_); 2502 partial_.reset(); 2503 truncated_ = false; 2504 return true; 2505 } 2506 } 2507 2508 // 304 is not expected here, but we'll spare the entry (unless it was 2509 // truncated). 2510 if (truncated_) 2511 failure = true; 2512 } 2513 2514 if (failure) { 2515 // We cannot truncate this entry, it has to be deleted. 2516 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2517 DoomPartialEntry(false); 2518 mode_ = NONE; 2519 if (!reading_ && !partial_->IsLastRange()) { 2520 // We'll attempt to issue another network request, this time without us 2521 // messing up the headers. 2522 partial_->RestoreHeaders(&custom_request_->extra_headers); 2523 partial_.reset(); 2524 truncated_ = false; 2525 return false; 2526 } 2527 LOG(WARNING) << "Failed to revalidate partial entry"; 2528 partial_.reset(); 2529 return true; 2530 } 2531 2532 IgnoreRangeRequest(); 2533 return true; 2534 } 2535 2536 void HttpCache::Transaction::IgnoreRangeRequest() { 2537 // We have a problem. We may or may not be reading already (in which case we 2538 // returned the headers), but we'll just pretend that this request is not 2539 // using the cache and see what happens. Most likely this is the first 2540 // response from the server (it's not changing its mind midway, right?). 2541 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2542 if (mode_ & WRITE) 2543 DoneWritingToEntry(mode_ != WRITE); 2544 else if (mode_ & READ && entry_) 2545 cache_->DoneReadingFromEntry(entry_, this); 2546 2547 partial_.reset(NULL); 2548 entry_ = NULL; 2549 mode_ = NONE; 2550 } 2551 2552 void HttpCache::Transaction::FixHeadersForHead() { 2553 if (response_.headers->response_code() == 206) { 2554 response_.headers->RemoveHeader("Content-Length"); 2555 response_.headers->RemoveHeader("Content-Range"); 2556 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK"); 2557 } 2558 } 2559 2560 void HttpCache::Transaction::FailRangeRequest() { 2561 response_ = *new_response_; 2562 partial_->FixResponseHeaders(response_.headers.get(), false); 2563 } 2564 2565 int HttpCache::Transaction::SetupEntryForRead() { 2566 if (network_trans_) 2567 ResetNetworkTransaction(); 2568 if (partial_.get()) { 2569 if (truncated_ || is_sparse_ || !invalid_range_) { 2570 // We are going to return the saved response headers to the caller, so 2571 // we may need to adjust them first. 2572 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 2573 return OK; 2574 } else { 2575 partial_.reset(); 2576 } 2577 } 2578 cache_->ConvertWriterToReader(entry_); 2579 mode_ = READ; 2580 2581 if (request_->method == "HEAD") 2582 FixHeadersForHead(); 2583 2584 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) 2585 next_state_ = STATE_CACHE_READ_METADATA; 2586 return OK; 2587 } 2588 2589 2590 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { 2591 read_buf_ = data; 2592 io_buf_len_ = data_len; 2593 next_state_ = STATE_NETWORK_READ; 2594 return DoLoop(OK); 2595 } 2596 2597 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { 2598 if (request_->method == "HEAD") 2599 return 0; 2600 2601 read_buf_ = data; 2602 io_buf_len_ = data_len; 2603 next_state_ = STATE_CACHE_READ_DATA; 2604 return DoLoop(OK); 2605 } 2606 2607 int HttpCache::Transaction::WriteToEntry(int index, int offset, 2608 IOBuffer* data, int data_len, 2609 const CompletionCallback& callback) { 2610 if (!entry_) 2611 return data_len; 2612 2613 int rv = 0; 2614 if (!partial_.get() || !data_len) { 2615 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, 2616 true); 2617 } else { 2618 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); 2619 } 2620 return rv; 2621 } 2622 2623 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { 2624 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 2625 if (!entry_) 2626 return OK; 2627 2628 // Do not cache no-store content (unless we are record mode). Do not cache 2629 // content with cert errors either. This is to prevent not reporting net 2630 // errors when loading a resource from the cache. When we load a page over 2631 // HTTPS with a cert error we show an SSL blocking page. If the user clicks 2632 // proceed we reload the resource ignoring the errors. The loaded resource 2633 // is then cached. If that resource is subsequently loaded from the cache, 2634 // no net error is reported (even though the cert status contains the actual 2635 // errors) and no SSL blocking page is shown. An alternative would be to 2636 // reverse-map the cert status to a net error and replay the net error. 2637 if ((cache_->mode() != RECORD && 2638 response_.headers->HasHeaderValue("cache-control", "no-store")) || 2639 net::IsCertStatusError(response_.ssl_info.cert_status)) { 2640 DoneWritingToEntry(false); 2641 if (net_log_.IsLogging()) 2642 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2643 return OK; 2644 } 2645 2646 // cert_cache() will be null if the CertCacheTrial field trial is disabled. 2647 if (cache_->cert_cache() && response_.ssl_info.is_valid()) 2648 WriteCertChain(); 2649 2650 // When writing headers, we normally only write the non-transient 2651 // headers; when in record mode, record everything. 2652 bool skip_transient_headers = (cache_->mode() != RECORD); 2653 2654 if (truncated) 2655 DCHECK_EQ(200, response_.headers->response_code()); 2656 2657 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2658 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2659 data->Done(); 2660 2661 io_buf_len_ = data->pickle()->size(); 2662 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), 2663 io_buf_len_, io_callback_, true); 2664 } 2665 2666 int HttpCache::Transaction::AppendResponseDataToEntry( 2667 IOBuffer* data, int data_len, const CompletionCallback& callback) { 2668 if (!entry_ || !data_len) 2669 return data_len; 2670 2671 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2672 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, 2673 callback); 2674 } 2675 2676 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2677 if (!entry_) 2678 return; 2679 2680 RecordHistograms(); 2681 2682 cache_->DoneWritingToEntry(entry_, success); 2683 entry_ = NULL; 2684 mode_ = NONE; // switch to 'pass through' mode 2685 } 2686 2687 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2688 DLOG(ERROR) << "ReadData failed: " << result; 2689 const int result_for_histogram = std::max(0, -result); 2690 if (restart) { 2691 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2692 result_for_histogram); 2693 } else { 2694 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 2695 result_for_histogram); 2696 } 2697 2698 // Avoid using this entry in the future. 2699 if (cache_.get()) 2700 cache_->DoomActiveEntry(cache_key_); 2701 2702 if (restart) { 2703 DCHECK(!reading_); 2704 DCHECK(!network_trans_.get()); 2705 cache_->DoneWithEntry(entry_, this, false); 2706 entry_ = NULL; 2707 is_sparse_ = false; 2708 partial_.reset(); 2709 next_state_ = STATE_GET_BACKEND; 2710 return OK; 2711 } 2712 2713 return ERR_CACHE_READ_FAILURE; 2714 } 2715 2716 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 2717 if (entry_lock_waiting_since_ != start_time) 2718 return; 2719 2720 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 2721 2722 if (!cache_) 2723 return; 2724 2725 cache_->RemovePendingTransaction(this); 2726 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 2727 } 2728 2729 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 2730 DVLOG(2) << "DoomPartialEntry"; 2731 int rv = cache_->DoomEntry(cache_key_, NULL); 2732 DCHECK_EQ(OK, rv); 2733 cache_->DoneWithEntry(entry_, this, false); 2734 entry_ = NULL; 2735 is_sparse_ = false; 2736 if (delete_object) 2737 partial_.reset(NULL); 2738 } 2739 2740 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { 2741 partial_->OnNetworkReadCompleted(result); 2742 2743 if (result == 0) { 2744 // We need to move on to the next range. 2745 ResetNetworkTransaction(); 2746 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 2747 } 2748 return result; 2749 } 2750 2751 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { 2752 partial_->OnCacheReadCompleted(result); 2753 2754 if (result == 0 && mode_ == READ_WRITE) { 2755 // We need to move on to the next range. 2756 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 2757 } else if (result < 0) { 2758 return OnCacheReadError(result, false); 2759 } 2760 return result; 2761 } 2762 2763 int HttpCache::Transaction::DoRestartPartialRequest() { 2764 // The stored data cannot be used. Get rid of it and restart this request. 2765 // We need to also reset the |truncated_| flag as a new entry is created. 2766 DoomPartialEntry(!range_requested_); 2767 mode_ = WRITE; 2768 truncated_ = false; 2769 next_state_ = STATE_INIT_ENTRY; 2770 return OK; 2771 } 2772 2773 void HttpCache::Transaction::ResetNetworkTransaction() { 2774 DCHECK(!old_network_trans_load_timing_); 2775 DCHECK(network_trans_); 2776 LoadTimingInfo load_timing; 2777 if (network_trans_->GetLoadTimingInfo(&load_timing)) 2778 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); 2779 total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); 2780 network_trans_.reset(); 2781 } 2782 2783 // Histogram data from the end of 2010 show the following distribution of 2784 // response headers: 2785 // 2786 // Content-Length............... 87% 2787 // Date......................... 98% 2788 // Last-Modified................ 49% 2789 // Etag......................... 19% 2790 // Accept-Ranges: bytes......... 25% 2791 // Accept-Ranges: none.......... 0.4% 2792 // Strong Validator............. 50% 2793 // Strong Validator + ranges.... 24% 2794 // Strong Validator + CL........ 49% 2795 // 2796 bool HttpCache::Transaction::CanResume(bool has_data) { 2797 // Double check that there is something worth keeping. 2798 if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex)) 2799 return false; 2800 2801 if (request_->method != "GET") 2802 return false; 2803 2804 // Note that if this is a 206, content-length was already fixed after calling 2805 // PartialData::ResponseHeadersOK(). 2806 if (response_.headers->GetContentLength() <= 0 || 2807 response_.headers->HasHeaderValue("Accept-Ranges", "none") || 2808 !response_.headers->HasStrongValidators()) { 2809 return false; 2810 } 2811 2812 return true; 2813 } 2814 2815 void HttpCache::Transaction::UpdateTransactionPattern( 2816 TransactionPattern new_transaction_pattern) { 2817 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2818 return; 2819 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED || 2820 new_transaction_pattern == PATTERN_NOT_COVERED); 2821 transaction_pattern_ = new_transaction_pattern; 2822 } 2823 2824 void HttpCache::Transaction::RecordHistograms() { 2825 DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_); 2826 if (!cache_.get() || !cache_->GetCurrentBackend() || 2827 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE || 2828 cache_->mode() != NORMAL || request_->method != "GET") { 2829 return; 2830 } 2831 UMA_HISTOGRAM_ENUMERATION( 2832 "HttpCache.Pattern", transaction_pattern_, PATTERN_MAX); 2833 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2834 return; 2835 DCHECK(!range_requested_); 2836 DCHECK(!first_cache_access_since_.is_null()); 2837 2838 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 2839 2840 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 2841 2842 bool did_send_request = !send_request_since_.is_null(); 2843 DCHECK( 2844 (did_send_request && 2845 (transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED || 2846 transaction_pattern_ == PATTERN_ENTRY_VALIDATED || 2847 transaction_pattern_ == PATTERN_ENTRY_UPDATED || 2848 transaction_pattern_ == PATTERN_ENTRY_CANT_CONDITIONALIZE)) || 2849 (!did_send_request && transaction_pattern_ == PATTERN_ENTRY_USED)); 2850 2851 if (!did_send_request) { 2852 DCHECK(transaction_pattern_ == PATTERN_ENTRY_USED); 2853 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time); 2854 return; 2855 } 2856 2857 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_; 2858 int before_send_percent = 2859 total_time.ToInternalValue() == 0 ? 0 2860 : before_send_time * 100 / total_time; 2861 DCHECK_LE(0, before_send_percent); 2862 DCHECK_GE(100, before_send_percent); 2863 2864 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time); 2865 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time); 2866 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_percent); 2867 2868 // TODO(gavinp): Remove or minimize these histograms, particularly the ones 2869 // below this comment after we have received initial data. 2870 switch (transaction_pattern_) { 2871 case PATTERN_ENTRY_CANT_CONDITIONALIZE: { 2872 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize", 2873 before_send_time); 2874 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize", 2875 before_send_percent); 2876 break; 2877 } 2878 case PATTERN_ENTRY_NOT_CACHED: { 2879 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time); 2880 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached", 2881 before_send_percent); 2882 break; 2883 } 2884 case PATTERN_ENTRY_VALIDATED: { 2885 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time); 2886 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated", 2887 before_send_percent); 2888 break; 2889 } 2890 case PATTERN_ENTRY_UPDATED: { 2891 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time); 2892 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated", 2893 before_send_percent); 2894 break; 2895 } 2896 default: 2897 NOTREACHED(); 2898 } 2899 } 2900 2901 void HttpCache::Transaction::OnIOComplete(int result) { 2902 DoLoop(result); 2903 } 2904 2905 } // namespace net 2906