| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_cache_transaction.h" | 5 #include "net/http/http_cache_transaction.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 | 8 |
| 9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 return false; | 94 return false; |
| 95 } | 95 } |
| 96 | 96 |
| 97 //----------------------------------------------------------------------------- | 97 //----------------------------------------------------------------------------- |
| 98 | 98 |
| 99 HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support) | 99 HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support) |
| 100 : next_state_(STATE_NONE), | 100 : next_state_(STATE_NONE), |
| 101 request_(NULL), | 101 request_(NULL), |
| 102 cache_(cache->AsWeakPtr()), | 102 cache_(cache->AsWeakPtr()), |
| 103 entry_(NULL), | 103 entry_(NULL), |
| 104 new_entry_(NULL), |
| 104 network_trans_(NULL), | 105 network_trans_(NULL), |
| 105 callback_(NULL), | 106 callback_(NULL), |
| 106 mode_(NONE), | 107 mode_(NONE), |
| 107 reading_(false), | 108 reading_(false), |
| 108 invalid_range_(false), | 109 invalid_range_(false), |
| 109 enable_range_support_(enable_range_support), | 110 enable_range_support_(enable_range_support), |
| 110 truncated_(false), | 111 truncated_(false), |
| 111 read_offset_(0), | 112 read_offset_(0), |
| 112 effective_load_flags_(0), | 113 effective_load_flags_(0), |
| 113 final_upload_progress_(0), | 114 final_upload_progress_(0), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 } | 150 } |
| 150 | 151 |
| 151 int HttpCache::Transaction::Start(const HttpRequestInfo* request, | 152 int HttpCache::Transaction::Start(const HttpRequestInfo* request, |
| 152 CompletionCallback* callback, | 153 CompletionCallback* callback, |
| 153 LoadLog* load_log) { | 154 LoadLog* load_log) { |
| 154 DCHECK(request); | 155 DCHECK(request); |
| 155 DCHECK(callback); | 156 DCHECK(callback); |
| 156 | 157 |
| 157 // Ensure that we only have one asynchronous call at a time. | 158 // Ensure that we only have one asynchronous call at a time. |
| 158 DCHECK(!callback_); | 159 DCHECK(!callback_); |
| 160 DCHECK(!reading_); |
| 161 DCHECK(!network_trans_.get()); |
| 162 DCHECK(!entry_); |
| 159 | 163 |
| 160 if (!cache_) | 164 if (!cache_) |
| 161 return ERR_UNEXPECTED; | 165 return ERR_UNEXPECTED; |
| 162 | 166 |
| 163 SetRequest(load_log, request); | 167 SetRequest(load_log, request); |
| 164 | 168 |
| 165 int rv; | 169 int rv; |
| 166 | 170 |
| 167 if (!ShouldPassThrough()) { | 171 if (!ShouldPassThrough()) { |
| 168 cache_key_ = cache_->GenerateCacheKey(request); | 172 cache_key_ = cache_->GenerateCacheKey(request); |
| 169 | 173 |
| 170 // requested cache access mode | 174 // Requested cache access mode. |
| 171 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { | 175 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { |
| 172 mode_ = READ; | 176 mode_ = READ; |
| 173 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { | 177 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { |
| 174 mode_ = WRITE; | 178 mode_ = WRITE; |
| 175 } else { | 179 } else { |
| 176 mode_ = READ_WRITE; | 180 mode_ = READ_WRITE; |
| 177 } | 181 } |
| 178 | 182 |
| 179 // Downgrade to UPDATE if the request has been externally conditionalized. | 183 // Downgrade to UPDATE if the request has been externally conditionalized. |
| 180 if (external_validation_.initialized) { | 184 if (external_validation_.initialized) { |
| 181 if (mode_ & WRITE) { | 185 if (mode_ & WRITE) { |
| 182 // Strip off the READ_DATA bit (and maybe add back a READ_META bit | 186 // Strip off the READ_DATA bit (and maybe add back a READ_META bit |
| 183 // in case READ was off). | 187 // in case READ was off). |
| 184 mode_ = UPDATE; | 188 mode_ = UPDATE; |
| 185 } else { | 189 } else { |
| 186 mode_ = NONE; | 190 mode_ = NONE; |
| 187 } | 191 } |
| 188 } | 192 } |
| 189 } | 193 } |
| 190 | 194 |
| 191 // if must use cache, then we must fail. this can happen for back/forward | 195 // If must use cache, then we must fail. This can happen for back/forward |
| 192 // navigations to a page generated via a form post. | 196 // navigations to a page generated via a form post. |
| 193 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) | 197 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) |
| 194 return ERR_CACHE_MISS; | 198 return ERR_CACHE_MISS; |
| 195 | 199 |
| 196 if (mode_ == NONE) { | 200 if (mode_ == NONE) { |
| 197 if (partial_.get()) | 201 if (partial_.get()) |
| 198 partial_->RestoreHeaders(&custom_request_->extra_headers); | 202 partial_->RestoreHeaders(&custom_request_->extra_headers); |
| 199 rv = BeginNetworkRequest(); | 203 rv = BeginNetworkRequest(); |
| 200 } else { | 204 } else { |
| 201 rv = AddToEntry(); | 205 rv = AddToEntry(); |
| 202 } | 206 } |
| 203 | 207 |
| 204 // setting this here allows us to check for the existance of a callback_ to | 208 // Setting this here allows us to check for the existance of a callback_ to |
| 205 // determine if we are still inside Start. | 209 // determine if we are still inside Start. |
| 206 if (rv == ERR_IO_PENDING) | 210 if (rv == ERR_IO_PENDING) |
| 207 callback_ = callback; | 211 callback_ = callback; |
| 208 | 212 |
| 209 return rv; | 213 return rv; |
| 210 } | 214 } |
| 211 | 215 |
| 212 int HttpCache::Transaction::RestartIgnoringLastError( | 216 int HttpCache::Transaction::RestartIgnoringLastError( |
| 213 CompletionCallback* callback) { | 217 CompletionCallback* callback) { |
| 214 DCHECK(callback); | 218 DCHECK(callback); |
| 215 | 219 |
| 216 // ensure that we only have one asynchronous call at a time. | 220 // Ensure that we only have one asynchronous call at a time. |
| 217 DCHECK(!callback_); | 221 DCHECK(!callback_); |
| 218 | 222 |
| 219 if (!cache_) | 223 if (!cache_) |
| 220 return ERR_UNEXPECTED; | 224 return ERR_UNEXPECTED; |
| 221 | 225 |
| 222 int rv = RestartNetworkRequest(); | 226 int rv = RestartNetworkRequest(); |
| 223 | 227 |
| 224 if (rv == ERR_IO_PENDING) | 228 if (rv == ERR_IO_PENDING) |
| 225 callback_ = callback; | 229 callback_ = callback; |
| 226 | 230 |
| 227 return rv; | 231 return rv; |
| 228 } | 232 } |
| 229 | 233 |
| 230 int HttpCache::Transaction::RestartWithCertificate( | 234 int HttpCache::Transaction::RestartWithCertificate( |
| 231 X509Certificate* client_cert, | 235 X509Certificate* client_cert, |
| 232 CompletionCallback* callback) { | 236 CompletionCallback* callback) { |
| 233 DCHECK(callback); | 237 DCHECK(callback); |
| 234 | 238 |
| 235 // ensure that we only have one asynchronous call at a time. | 239 // Ensure that we only have one asynchronous call at a time. |
| 236 DCHECK(!callback_); | 240 DCHECK(!callback_); |
| 237 | 241 |
| 238 if (!cache_) | 242 if (!cache_) |
| 239 return ERR_UNEXPECTED; | 243 return ERR_UNEXPECTED; |
| 240 | 244 |
| 241 int rv = RestartNetworkRequestWithCertificate(client_cert); | 245 int rv = RestartNetworkRequestWithCertificate(client_cert); |
| 242 | 246 |
| 243 if (rv == ERR_IO_PENDING) | 247 if (rv == ERR_IO_PENDING) |
| 244 callback_ = callback; | 248 callback_ = callback; |
| 245 | 249 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 return LOAD_STATE_WAITING_FOR_CACHE; | 347 return LOAD_STATE_WAITING_FOR_CACHE; |
| 344 } | 348 } |
| 345 | 349 |
| 346 uint64 HttpCache::Transaction::GetUploadProgress() const { | 350 uint64 HttpCache::Transaction::GetUploadProgress() const { |
| 347 if (network_trans_.get()) | 351 if (network_trans_.get()) |
| 348 return network_trans_->GetUploadProgress(); | 352 return network_trans_->GetUploadProgress(); |
| 349 return final_upload_progress_; | 353 return final_upload_progress_; |
| 350 } | 354 } |
| 351 | 355 |
| 352 int HttpCache::Transaction::AddToEntry() { | 356 int HttpCache::Transaction::AddToEntry() { |
| 353 ActiveEntry* entry = NULL; | 357 next_state_ = STATE_INIT_ENTRY; |
| 358 return DoLoop(OK); |
| 359 } |
| 360 |
| 361 int HttpCache::Transaction::DoInitEntry() { |
| 362 DCHECK(!new_entry_); |
| 354 | 363 |
| 355 if (!cache_) | 364 if (!cache_) |
| 356 return ERR_UNEXPECTED; | 365 return ERR_UNEXPECTED; |
| 357 | 366 |
| 358 if (mode_ == WRITE) { | 367 if (mode_ == WRITE) { |
| 359 cache_->DoomEntry(cache_key_); | 368 next_state_ = STATE_DOOM_ENTRY; |
| 360 } else { | 369 return OK; |
| 361 entry = cache_->FindActiveEntry(cache_key_); | 370 } |
| 362 if (!entry) { | |
| 363 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY); | |
| 364 entry = cache_->OpenEntry(cache_key_); | |
| 365 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY); | |
| 366 if (!entry) { | |
| 367 if (mode_ == READ_WRITE) { | |
| 368 mode_ = WRITE; | |
| 369 } else if (mode_ == UPDATE) { | |
| 370 // There is no cache entry to update; proceed without caching. | |
| 371 mode_ = NONE; | |
| 372 return BeginNetworkRequest(); | |
| 373 } else { | |
| 374 if (cache_->mode() == PLAYBACK) | |
| 375 DLOG(INFO) << "Playback Cache Miss: " << request_->url; | |
| 376 | 371 |
| 377 // entry does not exist, and not permitted to create a new entry, so | 372 new_entry_ = cache_->FindActiveEntry(cache_key_); |
| 378 // we must fail. | 373 if (!new_entry_) { |
| 379 return HandleResult(ERR_CACHE_MISS); | 374 next_state_ = STATE_OPEN_ENTRY; |
| 380 } | 375 return OK; |
| 381 } | |
| 382 } | |
| 383 } | 376 } |
| 384 | 377 |
| 385 if (mode_ == WRITE) { | 378 if (mode_ == WRITE) { |
| 386 DCHECK(!entry); | 379 next_state_ = STATE_CREATE_ENTRY; |
| 387 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY); | 380 return OK; |
| 388 entry = cache_->CreateEntry(cache_key_); | |
| 389 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY); | |
| 390 if (!entry) { | |
| 391 DLOG(WARNING) << "unable to create cache entry"; | |
| 392 mode_ = NONE; | |
| 393 if (partial_.get()) | |
| 394 partial_->RestoreHeaders(&custom_request_->extra_headers); | |
| 395 return BeginNetworkRequest(); | |
| 396 } | |
| 397 } | 381 } |
| 398 | 382 |
| 383 next_state_ = STATE_ADD_TO_ENTRY; |
| 384 return OK; |
| 385 } |
| 399 | 386 |
| 387 int HttpCache::Transaction::DoDoomEntry() { |
| 388 next_state_ = STATE_DOOM_ENTRY_COMPLETE; |
| 389 cache_->DoomEntry(cache_key_); |
| 390 return OK; |
| 391 } |
| 392 |
| 393 int HttpCache::Transaction::DoDoomEntryComplete() { |
| 394 next_state_ = STATE_CREATE_ENTRY; |
| 395 return OK; |
| 396 } |
| 397 |
| 398 int HttpCache::Transaction::DoOpenEntry() { |
| 399 DCHECK(!new_entry_); |
| 400 next_state_ = STATE_OPEN_ENTRY_COMPLETE; |
| 401 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY); |
| 402 new_entry_ = cache_->OpenEntry(cache_key_); |
| 403 return OK; |
| 404 } |
| 405 |
| 406 int HttpCache::Transaction::DoOpenEntryComplete() { |
| 407 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY); |
| 408 if (new_entry_) { |
| 409 next_state_ = STATE_ADD_TO_ENTRY; |
| 410 return OK; |
| 411 } |
| 412 |
| 413 if (mode_ == READ_WRITE) { |
| 414 mode_ = WRITE; |
| 415 next_state_ = STATE_CREATE_ENTRY; |
| 416 return OK; |
| 417 } |
| 418 if (mode_ == UPDATE) { |
| 419 // There is no cache entry to update; proceed without caching. |
| 420 mode_ = NONE; |
| 421 next_state_ = STATE_SEND_REQUEST; |
| 422 return OK; |
| 423 } |
| 424 if (cache_->mode() == PLAYBACK) |
| 425 DLOG(INFO) << "Playback Cache Miss: " << request_->url; |
| 426 |
| 427 // The entry does not exist, and we are not permitted to create a new entry, |
| 428 // so we must fail. |
| 429 return ERR_CACHE_MISS; |
| 430 } |
| 431 |
| 432 int HttpCache::Transaction::DoCreateEntry() { |
| 433 DCHECK(!new_entry_); |
| 434 next_state_ = STATE_CREATE_ENTRY_COMPLETE; |
| 435 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY); |
| 436 new_entry_ = cache_->CreateEntry(cache_key_); |
| 437 return OK; |
| 438 } |
| 439 |
| 440 int HttpCache::Transaction::DoCreateEntryComplete() { |
| 441 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY); |
| 442 next_state_ = STATE_ADD_TO_ENTRY; |
| 443 if (!new_entry_) { |
| 444 // We have a race here: Maybe we failed to open the entry and decided to |
| 445 // create one, but by the time we called create, another transaction already |
| 446 // created the entry. If we want to eliminate this issue, we need an atomic |
| 447 // OpenOrCreate() method exposed by the disk cache. |
| 448 DLOG(WARNING) << "Unable to create cache entry"; |
| 449 mode_ = NONE; |
| 450 if (partial_.get()) |
| 451 partial_->RestoreHeaders(&custom_request_->extra_headers); |
| 452 next_state_ = STATE_SEND_REQUEST; |
| 453 } |
| 454 return OK; |
| 455 } |
| 456 |
| 457 int HttpCache::Transaction::DoAddToEntry() { |
| 458 DCHECK(new_entry_); |
| 400 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING); | 459 LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING); |
| 401 return cache_->AddTransactionToEntry(entry, this); | 460 int rv = cache_->AddTransactionToEntry(new_entry_, this); |
| 461 new_entry_ = NULL; |
| 462 return rv; |
| 402 } | 463 } |
| 403 | 464 |
| 404 int HttpCache::Transaction::EntryAvailable(ActiveEntry* entry) { | 465 int HttpCache::Transaction::EntryAvailable(ActiveEntry* entry) { |
| 405 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING); | 466 LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING); |
| 467 entry_ = entry; |
| 406 | 468 |
| 469 next_state_ = STATE_ENTRY_AVAILABLE; |
| 470 if (new_entry_) { |
| 471 // We are inside AddTransactionToEntry() so avoid reentering DoLoop(). |
| 472 DCHECK_EQ(new_entry_, entry); |
| 473 return OK; |
| 474 } |
| 475 return DoLoop(OK); |
| 476 } |
| 477 |
| 478 int HttpCache::Transaction::DoEntryAvailable() { |
| 407 // We now have access to the cache entry. | 479 // We now have access to the cache entry. |
| 408 // | 480 // |
| 409 // o if we are the writer for the transaction, then we can start the network | 481 // o if we are the writer for the transaction, then we can start the network |
| 410 // transaction. | 482 // transaction. |
| 411 // | 483 // |
| 412 // o if we are a reader for the transaction, then we can start reading the | 484 // o if we are a reader for the transaction, then we can start reading the |
| 413 // cache entry. | 485 // cache entry. |
| 414 // | 486 // |
| 415 // o if we can read or write, then we should check if the cache entry needs | 487 // o if we can read or write, then we should check if the cache entry needs |
| 416 // to be validated and then issue a network request if needed or just read | 488 // to be validated and then issue a network request if needed or just read |
| 417 // from the cache if the cache entry is already valid. | 489 // from the cache if the cache entry is already valid. |
| 418 // | 490 // |
| 419 // o if we are set to UPDATE, then we are handling an externally | 491 // o if we are set to UPDATE, then we are handling an externally |
| 420 // conditionalized request (if-modified-since / if-none-match). We read | 492 // conditionalized request (if-modified-since / if-none-match). We read |
| 421 // the cache entry, and check if the request headers define a validation | 493 // the cache entry, and check if the request headers define a validation |
| 422 // request. | 494 // request. |
| 423 // | 495 // |
| 496 DCHECK(!new_entry_); |
| 424 int rv; | 497 int rv; |
| 425 entry_ = entry; | |
| 426 switch (mode_) { | 498 switch (mode_) { |
| 427 case READ: | 499 case READ: |
| 428 rv = BeginCacheRead(); | 500 rv = BeginCacheRead(); |
| 429 break; | 501 break; |
| 430 case WRITE: | 502 case WRITE: |
| 431 if (partial_.get()) | 503 if (partial_.get()) |
| 432 partial_->RestoreHeaders(&custom_request_->extra_headers); | 504 partial_->RestoreHeaders(&custom_request_->extra_headers); |
| 433 rv = BeginNetworkRequest(); | 505 next_state_ = STATE_SEND_REQUEST; |
| 506 rv = OK; |
| 434 break; | 507 break; |
| 435 case READ_WRITE: | 508 case READ_WRITE: |
| 436 rv = BeginPartialCacheValidation(); | 509 rv = BeginPartialCacheValidation(); |
| 437 break; | 510 break; |
| 438 case UPDATE: | 511 case UPDATE: |
| 439 rv = BeginExternallyConditionalizedRequest(); | 512 rv = BeginExternallyConditionalizedRequest(); |
| 440 break; | 513 break; |
| 441 default: | 514 default: |
| 442 NOTREACHED(); | 515 NOTREACHED(); |
| 443 rv = ERR_FAILED; | 516 rv = ERR_FAILED; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 case STATE_SEND_REQUEST_COMPLETE: | 566 case STATE_SEND_REQUEST_COMPLETE: |
| 494 rv = DoSendRequestComplete(rv); | 567 rv = DoSendRequestComplete(rv); |
| 495 break; | 568 break; |
| 496 case STATE_NETWORK_READ: | 569 case STATE_NETWORK_READ: |
| 497 DCHECK_EQ(OK, rv); | 570 DCHECK_EQ(OK, rv); |
| 498 rv = DoNetworkRead(); | 571 rv = DoNetworkRead(); |
| 499 break; | 572 break; |
| 500 case STATE_NETWORK_READ_COMPLETE: | 573 case STATE_NETWORK_READ_COMPLETE: |
| 501 rv = DoNetworkReadComplete(rv); | 574 rv = DoNetworkReadComplete(rv); |
| 502 break; | 575 break; |
| 576 case STATE_INIT_ENTRY: |
| 577 DCHECK_EQ(OK, rv); |
| 578 rv = DoInitEntry(); |
| 579 break; |
| 580 case STATE_OPEN_ENTRY: |
| 581 DCHECK_EQ(OK, rv); |
| 582 rv = DoOpenEntry(); |
| 583 break; |
| 584 case STATE_OPEN_ENTRY_COMPLETE: |
| 585 DCHECK_EQ(OK, rv); |
| 586 rv = DoOpenEntryComplete(); |
| 587 break; |
| 588 case STATE_CREATE_ENTRY: |
| 589 DCHECK_EQ(OK, rv); |
| 590 rv = DoCreateEntry(); |
| 591 break; |
| 592 case STATE_CREATE_ENTRY_COMPLETE: |
| 593 DCHECK_EQ(OK, rv); |
| 594 rv = DoCreateEntryComplete(); |
| 595 break; |
| 596 case STATE_DOOM_ENTRY: |
| 597 DCHECK_EQ(OK, rv); |
| 598 rv = DoDoomEntry(); |
| 599 break; |
| 600 case STATE_DOOM_ENTRY_COMPLETE: |
| 601 DCHECK_EQ(OK, rv); |
| 602 rv = DoDoomEntryComplete(); |
| 603 break; |
| 604 case STATE_ADD_TO_ENTRY: |
| 605 DCHECK_EQ(OK, rv); |
| 606 rv = DoAddToEntry(); |
| 607 break; |
| 608 case STATE_ENTRY_AVAILABLE: |
| 609 DCHECK_EQ(OK, rv); |
| 610 rv = DoEntryAvailable(); |
| 611 break; |
| 612 case STATE_PARTIAL_CACHE_VALIDATION: |
| 613 DCHECK_EQ(OK, rv); |
| 614 rv = DoPartialCacheValidation(); |
| 615 break; |
| 503 case STATE_CACHE_QUERY_DATA: | 616 case STATE_CACHE_QUERY_DATA: |
| 504 DCHECK_EQ(OK, rv); | 617 DCHECK_EQ(OK, rv); |
| 505 rv = DoCacheQueryData(); | 618 rv = DoCacheQueryData(); |
| 506 break; | 619 break; |
| 507 case STATE_CACHE_QUERY_DATA_COMPLETE: | 620 case STATE_CACHE_QUERY_DATA_COMPLETE: |
| 508 rv = DoCacheQueryDataComplete(rv); | 621 rv = DoCacheQueryDataComplete(rv); |
| 509 break; | 622 break; |
| 510 case STATE_CACHE_READ_DATA: | 623 case STATE_CACHE_READ_DATA: |
| 511 DCHECK_EQ(OK, rv); | 624 DCHECK_EQ(OK, rv); |
| 512 rv = DoCacheReadData(); | 625 rv = DoCacheReadData(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 // TODO(darin): add support for caching HEAD responses | 787 // TODO(darin): add support for caching HEAD responses |
| 675 return true; | 788 return true; |
| 676 } | 789 } |
| 677 | 790 |
| 678 int HttpCache::Transaction::BeginCacheRead() { | 791 int HttpCache::Transaction::BeginCacheRead() { |
| 679 DCHECK(mode_ == READ); | 792 DCHECK(mode_ == READ); |
| 680 | 793 |
| 681 // Read response headers. | 794 // Read response headers. |
| 682 int rv = ReadResponseInfoFromEntry(); | 795 int rv = ReadResponseInfoFromEntry(); |
| 683 if (rv != OK) | 796 if (rv != OK) |
| 684 return HandleResult(rv); | 797 return rv; |
| 685 | 798 |
| 686 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. | 799 // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. |
| 687 if (response_.headers->response_code() == 206 || partial_.get()) { | 800 if (response_.headers->response_code() == 206 || partial_.get()) { |
| 688 NOTREACHED(); | 801 NOTREACHED(); |
| 689 return HandleResult(ERR_CACHE_MISS); | 802 return ERR_CACHE_MISS; |
| 690 } | 803 } |
| 691 | 804 |
| 692 // We don't have the whole resource. | 805 // We don't have the whole resource. |
| 693 if (truncated_) | 806 if (truncated_) |
| 694 return HandleResult(ERR_CACHE_MISS); | 807 return ERR_CACHE_MISS; |
| 695 | 808 |
| 696 return HandleResult(rv); | 809 return rv; |
| 697 } | 810 } |
| 698 | 811 |
| 699 int HttpCache::Transaction::BeginCacheValidation() { | 812 int HttpCache::Transaction::BeginCacheValidation() { |
| 700 DCHECK(mode_ == READ_WRITE); | 813 DCHECK(mode_ == READ_WRITE); |
| 701 | 814 |
| 702 if ((effective_load_flags_ & LOAD_PREFERRING_CACHE || | 815 if ((effective_load_flags_ & LOAD_PREFERRING_CACHE || |
| 703 !RequiresValidation()) && !partial_.get()) { | 816 !RequiresValidation()) && !partial_.get()) { |
| 704 cache_->ConvertWriterToReader(entry_); | 817 cache_->ConvertWriterToReader(entry_); |
| 705 mode_ = READ; | 818 mode_ = READ; |
| 706 } else { | 819 } else { |
| 707 // Make the network request conditional, to see if we may reuse our cached | 820 // Make the network request conditional, to see if we may reuse our cached |
| 708 // response. If we cannot do so, then we just resort to a normal fetch. | 821 // response. If we cannot do so, then we just resort to a normal fetch. |
| 709 // Our mode remains READ_WRITE for a conditional request. We'll switch to | 822 // Our mode remains READ_WRITE for a conditional request. We'll switch to |
| 710 // either READ or WRITE mode once we hear back from the server. | 823 // either READ or WRITE mode once we hear back from the server. |
| 711 if (!ConditionalizeRequest()) | 824 if (!ConditionalizeRequest()) |
| 712 mode_ = WRITE; | 825 mode_ = WRITE; |
| 713 return BeginNetworkRequest(); | 826 next_state_ = STATE_SEND_REQUEST; |
| 714 } | 827 } |
| 715 return HandleResult(OK); | 828 return OK; |
| 716 } | 829 } |
| 717 | 830 |
| 718 int HttpCache::Transaction::BeginPartialCacheValidation() { | 831 int HttpCache::Transaction::BeginPartialCacheValidation() { |
| 719 DCHECK(mode_ == READ_WRITE); | 832 DCHECK(mode_ == READ_WRITE); |
| 720 | 833 |
| 721 int rv = ReadResponseInfoFromEntry(); | 834 int rv = ReadResponseInfoFromEntry(); |
| 722 if (rv != OK) { | 835 if (rv != OK) { |
| 723 DCHECK(rv != ERR_IO_PENDING); | 836 DCHECK(rv != ERR_IO_PENDING); |
| 724 return HandleResult(rv); | 837 return rv; |
| 725 } | 838 } |
| 726 | 839 |
| 727 if (response_.headers->response_code() != 206 && !partial_.get() && | 840 if (response_.headers->response_code() != 206 && !partial_.get() && |
| 728 !truncated_) | 841 !truncated_) |
| 729 return BeginCacheValidation(); | 842 return BeginCacheValidation(); |
| 730 | 843 |
| 731 if (!enable_range_support_) | 844 if (!enable_range_support_) |
| 732 return BeginCacheValidation(); | 845 return BeginCacheValidation(); |
| 733 | 846 |
| 734 bool byte_range_requested = partial_.get() != NULL; | 847 bool byte_range_requested = partial_.get() != NULL; |
| 735 if (byte_range_requested) { | 848 if (byte_range_requested) { |
| 736 next_state_ = STATE_CACHE_QUERY_DATA; | 849 next_state_ = STATE_CACHE_QUERY_DATA; |
| 737 return DoLoop(OK); | 850 return OK; |
| 738 } | 851 } |
| 739 // The request is not for a range, but we have stored just ranges. | 852 // The request is not for a range, but we have stored just ranges. |
| 740 partial_.reset(new PartialData()); | 853 partial_.reset(new PartialData()); |
| 741 partial_->SetHeaders(request_->extra_headers); | 854 partial_->SetHeaders(request_->extra_headers); |
| 742 if (!custom_request_.get()) { | 855 if (!custom_request_.get()) { |
| 743 custom_request_.reset(new HttpRequestInfo(*request_)); | 856 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 744 request_ = custom_request_.get(); | 857 request_ = custom_request_.get(); |
| 745 } | 858 } |
| 746 | 859 |
| 747 return ValidateEntryHeadersAndContinue(false); | 860 return ValidateEntryHeadersAndContinue(false); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 769 bool byte_range_requested) { | 882 bool byte_range_requested) { |
| 770 DCHECK(mode_ == READ_WRITE); | 883 DCHECK(mode_ == READ_WRITE); |
| 771 | 884 |
| 772 if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry, | 885 if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry, |
| 773 truncated_)) { | 886 truncated_)) { |
| 774 // The stored data cannot be used. Get rid of it and restart this request. | 887 // The stored data cannot be used. Get rid of it and restart this request. |
| 775 // We need to also reset the |truncated_| flag as a new entry is created. | 888 // We need to also reset the |truncated_| flag as a new entry is created. |
| 776 DoomPartialEntry(!byte_range_requested); | 889 DoomPartialEntry(!byte_range_requested); |
| 777 mode_ = WRITE; | 890 mode_ = WRITE; |
| 778 truncated_ = false; | 891 truncated_ = false; |
| 779 return AddToEntry(); | 892 next_state_ = STATE_INIT_ENTRY; |
| 893 return OK; |
| 780 } | 894 } |
| 781 | 895 |
| 782 if (!partial_->IsRequestedRangeOK()) { | 896 if (!partial_->IsRequestedRangeOK()) { |
| 783 // The stored data is fine, but the request may be invalid. | 897 // The stored data is fine, but the request may be invalid. |
| 784 invalid_range_ = true; | 898 invalid_range_ = true; |
| 785 } | 899 } |
| 786 | 900 |
| 787 return ContinuePartialCacheValidation(); | 901 next_state_ = STATE_PARTIAL_CACHE_VALIDATION; |
| 902 return OK; |
| 788 } | 903 } |
| 789 | 904 |
| 790 int HttpCache::Transaction::ContinuePartialCacheValidation() { | 905 int HttpCache::Transaction::DoPartialCacheValidation() { |
| 791 DCHECK(mode_ == READ_WRITE); | 906 if (mode_ == NONE) |
| 907 return OK; |
| 908 |
| 792 int rv = partial_->PrepareCacheValidation(entry_->disk_entry, | 909 int rv = partial_->PrepareCacheValidation(entry_->disk_entry, |
| 793 &custom_request_->extra_headers); | 910 &custom_request_->extra_headers); |
| 794 | 911 |
| 795 if (!rv) { | 912 if (!rv) { |
| 796 // Don't invoke the callback before telling the cache we're done. | 913 // This is the end of the request. |
| 914 if (mode_ & WRITE) { |
| 915 DoneWritingToEntry(true); |
| 916 } else { |
| 917 cache_->DoneReadingFromEntry(entry_, this); |
| 918 entry_ = NULL; |
| 919 } |
| 797 return rv; | 920 return rv; |
| 798 } | 921 } |
| 799 | 922 |
| 800 if (rv < 0) { | 923 if (rv < 0) { |
| 801 DCHECK(rv != ERR_IO_PENDING); | 924 DCHECK(rv != ERR_IO_PENDING); |
| 802 return HandleResult(rv); | 925 return rv; |
| 803 } | 926 } |
| 804 | 927 |
| 805 if (reading_ && partial_->IsCurrentRangeCached()) { | 928 if (reading_ && partial_->IsCurrentRangeCached()) { |
| 806 rv = ReadFromEntry(read_buf_, read_buf_len_); | 929 next_state_ = STATE_CACHE_READ_DATA; |
| 807 | 930 return OK; |
| 808 // We are supposed to hanlde errors here. | |
| 809 if (rv < 0 && rv != ERR_IO_PENDING) | |
| 810 HandleResult(rv); | |
| 811 return rv; | |
| 812 } | 931 } |
| 813 | 932 |
| 814 return BeginCacheValidation(); | 933 return BeginCacheValidation(); |
| 815 } | 934 } |
| 816 | 935 |
| 817 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { | 936 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { |
| 818 DCHECK_EQ(UPDATE, mode_); | 937 DCHECK_EQ(UPDATE, mode_); |
| 819 DCHECK(external_validation_.initialized); | 938 DCHECK(external_validation_.initialized); |
| 820 | 939 |
| 821 // Read the cached response. | 940 // Read the cached response. |
| 822 int rv = ReadResponseInfoFromEntry(); | 941 int rv = ReadResponseInfoFromEntry(); |
| 823 if (rv != OK) { | 942 if (rv != OK) { |
| 824 DCHECK(rv != ERR_IO_PENDING); | 943 DCHECK(rv != ERR_IO_PENDING); |
| 825 return HandleResult(rv); | 944 return rv; |
| 826 } | 945 } |
| 827 | 946 |
| 828 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) { | 947 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) { |
| 829 if (external_validation_.values[i].empty()) | 948 if (external_validation_.values[i].empty()) |
| 830 continue; | 949 continue; |
| 831 // Retrieve either the cached response's "etag" or "last-modified" header. | 950 // Retrieve either the cached response's "etag" or "last-modified" header. |
| 832 std::string validator; | 951 std::string validator; |
| 833 response_.headers->EnumerateHeader( | 952 response_.headers->EnumerateHeader( |
| 834 NULL, | 953 NULL, |
| 835 kValidationHeaders[i].related_response_header_name, | 954 kValidationHeaders[i].related_response_header_name, |
| 836 &validator); | 955 &validator); |
| 837 | 956 |
| 838 if (response_.headers->response_code() != 200 || truncated_ || | 957 if (response_.headers->response_code() != 200 || truncated_ || |
| 839 validator.empty() || validator != external_validation_.values[i]) { | 958 validator.empty() || validator != external_validation_.values[i]) { |
| 840 // The externally conditionalized request is not a validation request | 959 // The externally conditionalized request is not a validation request |
| 841 // for our existing cache entry. Proceed with caching disabled. | 960 // for our existing cache entry. Proceed with caching disabled. |
| 842 DoneWritingToEntry(true); | 961 DoneWritingToEntry(true); |
| 843 } | 962 } |
| 844 } | 963 } |
| 845 | 964 |
| 846 return BeginNetworkRequest(); | 965 next_state_ = STATE_SEND_REQUEST; |
| 966 return OK; |
| 847 } | 967 } |
| 848 | 968 |
| 849 int HttpCache::Transaction::BeginNetworkRequest() { | 969 int HttpCache::Transaction::BeginNetworkRequest() { |
| 850 next_state_ = STATE_SEND_REQUEST; | 970 next_state_ = STATE_SEND_REQUEST; |
| 851 return DoLoop(OK); | 971 return DoLoop(OK); |
| 852 } | 972 } |
| 853 | 973 |
| 854 int HttpCache::Transaction::DoSendRequest() { | 974 int HttpCache::Transaction::DoSendRequest() { |
| 855 DCHECK(mode_ & WRITE || mode_ == NONE); | 975 DCHECK(mode_ & WRITE || mode_ == NONE); |
| 856 DCHECK(!network_trans_.get()); | 976 DCHECK(!network_trans_.get()); |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { | 1374 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { |
| 1255 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; | 1375 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; |
| 1256 cache_callback_->AddRef(); // Balanced in DoCacheWriteDataComplete. | 1376 cache_callback_->AddRef(); // Balanced in DoCacheWriteDataComplete. |
| 1257 | 1377 |
| 1258 return AppendResponseDataToEntry(read_buf_, num_bytes, cache_callback_); | 1378 return AppendResponseDataToEntry(read_buf_, num_bytes, cache_callback_); |
| 1259 } | 1379 } |
| 1260 | 1380 |
| 1261 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { | 1381 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { |
| 1262 partial_->OnNetworkReadCompleted(result); | 1382 partial_->OnNetworkReadCompleted(result); |
| 1263 | 1383 |
| 1264 if (result == 0) { // End of file. | 1384 if (result == 0) { |
| 1265 if (mode_ == READ_WRITE) { | 1385 // We need to move on to the next range. |
| 1266 // We need to move on to the next range. | 1386 network_trans_.reset(); |
| 1267 network_trans_.reset(); | 1387 next_state_ = STATE_PARTIAL_CACHE_VALIDATION; |
| 1268 result = ContinuePartialCacheValidation(); | |
| 1269 if (result != OK) | |
| 1270 // Any error was already handled. | |
| 1271 return result; | |
| 1272 } | |
| 1273 DoneWritingToEntry(true); | |
| 1274 } | 1388 } |
| 1275 return result; | 1389 return result; |
| 1276 } | 1390 } |
| 1277 | 1391 |
| 1278 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { | 1392 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { |
| 1279 cache_callback_->Release(); // Balance the AddRef from DoCacheReadData. | 1393 cache_callback_->Release(); // Balance the AddRef from DoCacheReadData. |
| 1280 | 1394 |
| 1281 if (!cache_) | 1395 if (!cache_) |
| 1282 return ERR_UNEXPECTED; | 1396 return ERR_UNEXPECTED; |
| 1283 | 1397 |
| 1284 if (partial_.get()) | 1398 if (partial_.get()) |
| 1285 return DoPartialCacheReadCompleted(result); | 1399 return DoPartialCacheReadCompleted(result); |
| 1286 | 1400 |
| 1287 if (result > 0) { | 1401 if (result > 0) { |
| 1288 read_offset_ += result; | 1402 read_offset_ += result; |
| 1289 } else if (result == 0) { // End of file. | 1403 } else if (result == 0) { // End of file. |
| 1290 cache_->DoneReadingFromEntry(entry_, this); | 1404 cache_->DoneReadingFromEntry(entry_, this); |
| 1291 entry_ = NULL; | 1405 entry_ = NULL; |
| 1292 } | 1406 } |
| 1293 return result; | 1407 return result; |
| 1294 } | 1408 } |
| 1295 | 1409 |
| 1296 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { | 1410 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { |
| 1297 partial_->OnCacheReadCompleted(result); | 1411 partial_->OnCacheReadCompleted(result); |
| 1298 | 1412 |
| 1299 if (result == 0) { // End of file. | 1413 if (result == 0 && mode_ == READ_WRITE) { |
| 1300 if (partial_.get() && mode_ == READ_WRITE) { | 1414 // We need to move on to the next range. |
| 1301 // We need to move on to the next range. | 1415 next_state_ = STATE_PARTIAL_CACHE_VALIDATION; |
| 1302 result = ContinuePartialCacheValidation(); | |
| 1303 if (result != OK || !entry_) { | |
| 1304 // Any error was already handled. | |
| 1305 return result; | |
| 1306 } | |
| 1307 cache_->ConvertWriterToReader(entry_); | |
| 1308 } | |
| 1309 cache_->DoneReadingFromEntry(entry_, this); | |
| 1310 entry_ = NULL; | |
| 1311 } | 1416 } |
| 1312 return result; | 1417 return result; |
| 1313 } | 1418 } |
| 1314 | 1419 |
| 1315 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { | 1420 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { |
| 1316 // Balance the AddRef from DoCacheWriteData. | 1421 // Balance the AddRef from DoCacheWriteData. |
| 1317 cache_callback_->Release(); | 1422 cache_callback_->Release(); |
| 1318 if (!cache_) | 1423 if (!cache_) |
| 1319 return ERR_UNEXPECTED; | 1424 return ERR_UNEXPECTED; |
| 1320 | 1425 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 // Truncate response data. | 1518 // Truncate response data. |
| 1414 TruncateResponseData(); | 1519 TruncateResponseData(); |
| 1415 | 1520 |
| 1416 // If this response is a redirect, then we can stop writing now. (We | 1521 // If this response is a redirect, then we can stop writing now. (We |
| 1417 // don't need to cache the response body of a redirect.) | 1522 // don't need to cache the response body of a redirect.) |
| 1418 if (response_.headers->IsRedirect(NULL)) | 1523 if (response_.headers->IsRedirect(NULL)) |
| 1419 DoneWritingToEntry(true); | 1524 DoneWritingToEntry(true); |
| 1420 } | 1525 } |
| 1421 if (reading_ && partial_.get()) { | 1526 if (reading_ && partial_.get()) { |
| 1422 if (network_trans_.get()) { | 1527 if (network_trans_.get()) { |
| 1423 next_state_ = STATE_NETWORK_READ_COMPLETE; | 1528 next_state_ = STATE_NETWORK_READ; |
| 1424 result = ReadFromNetwork(read_buf_, read_buf_len_); | |
| 1425 } else { | 1529 } else { |
| 1426 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; | 1530 next_state_ = STATE_CACHE_READ_DATA; |
| 1427 result = ReadFromEntry(read_buf_, read_buf_len_); | |
| 1428 } | 1531 } |
| 1429 if (result >= 0 || result == ERR_IO_PENDING) { | 1532 result = OK; |
| 1430 // Keep looping. | |
| 1431 return result; | |
| 1432 } else { | |
| 1433 // Don't keep looping when we return. | |
| 1434 next_state_ = STATE_NONE; | |
| 1435 } | |
| 1436 } else if (mode_ != NONE && partial_.get()) { | 1533 } else if (mode_ != NONE && partial_.get()) { |
| 1437 // We are about to return the headers for a byte-range request to the | 1534 // We are about to return the headers for a byte-range request to the |
| 1438 // user, so let's fix them. | 1535 // user, so let's fix them. |
| 1439 partial_->FixResponseHeaders(response_.headers); | 1536 partial_->FixResponseHeaders(response_.headers); |
| 1440 } | 1537 } |
| 1441 } | 1538 } |
| 1442 } else if (IsCertificateError(result)) { | 1539 } else if (IsCertificateError(result)) { |
| 1443 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); | 1540 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); |
| 1444 // If we get a certificate error, then there is a certificate in ssl_info, | 1541 // If we get a certificate error, then there is a certificate in ssl_info, |
| 1445 // so GetResponseInfo() should never returns NULL here. | 1542 // so GetResponseInfo() should never returns NULL here. |
| 1446 DCHECK(response); | 1543 DCHECK(response); |
| 1447 response_.ssl_info = response->ssl_info; | 1544 response_.ssl_info = response->ssl_info; |
| 1448 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 1545 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
| 1449 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); | 1546 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); |
| 1450 DCHECK(response); | 1547 DCHECK(response); |
| 1451 response_.cert_request_info = response->cert_request_info; | 1548 response_.cert_request_info = response->cert_request_info; |
| 1452 } | 1549 } |
| 1453 return result; | 1550 return result; |
| 1454 } | 1551 } |
| 1455 | 1552 |
| 1456 void HttpCache::Transaction::OnIOComplete(int result) { | 1553 void HttpCache::Transaction::OnIOComplete(int result) { |
| 1457 DoLoop(result); | 1554 DoLoop(result); |
| 1458 } | 1555 } |
| 1459 | 1556 |
| 1460 } // namespace net | 1557 } // namespace net |
| OLD | NEW |