Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/partial_data.h" | 5 #include "net/http/partial_data.h" |
| 6 | 6 |
| 7 #include <limits> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 9 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 13 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 14 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 15 #include "net/disk_cache/disk_cache.h" | 17 #include "net/disk_cache/disk_cache.h" |
| 16 #include "net/http/http_response_headers.h" | 18 #include "net/http/http_response_headers.h" |
| 17 #include "net/http/http_util.h" | 19 #include "net/http/http_util.h" |
| 18 | 20 |
| 19 namespace net { | 21 namespace net { |
| 20 | 22 |
| 21 namespace { | 23 namespace { |
| 22 | 24 |
| 23 // The headers that we have to process. | 25 // The headers that we have to process. |
| 24 const char kLengthHeader[] = "Content-Length"; | 26 const char kLengthHeader[] = "Content-Length"; |
| 25 const char kRangeHeader[] = "Content-Range"; | 27 const char kRangeHeader[] = "Content-Range"; |
| 26 const int kDataStream = 1; | 28 const int kDataStream = 1; |
| 27 | 29 |
| 28 } // namespace | 30 } // namespace |
| 29 | 31 |
| 32 // static | |
| 33 const int64 PartialData::kUnbounded = std::numeric_limits<int64>::max(); | |
| 34 | |
| 30 PartialData::PartialData() | 35 PartialData::PartialData() |
| 31 : current_range_start_(0), | 36 : current_range_start_(0), |
| 32 current_range_end_(0), | 37 current_range_end_(0), |
| 33 cached_start_(0), | 38 cached_start_(0), |
| 34 resource_size_(0), | 39 resource_size_(0), |
| 35 cached_min_len_(0), | 40 cached_min_len_(0), |
| 36 range_present_(false), | 41 range_present_(false), |
| 37 final_range_(false), | 42 final_range_(false), |
| 38 sparse_entry_(true), | 43 sparse_entry_(true), |
| 39 truncated_(false), | 44 truncated_(false), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 HttpByteRange::Bounded( | 92 HttpByteRange::Bounded( |
| 88 current_range_start_, end).GetHeaderValue()); | 93 current_range_start_, end).GetHeaderValue()); |
| 89 } | 94 } |
| 90 } | 95 } |
| 91 | 96 |
| 92 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, | 97 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, |
| 93 const CompletionCallback& callback) { | 98 const CompletionCallback& callback) { |
| 94 DCHECK_GE(current_range_start_, 0); | 99 DCHECK_GE(current_range_start_, 0); |
| 95 | 100 |
| 96 // Scan the disk cache for the first cached portion within this range. | 101 // Scan the disk cache for the first cached portion within this range. |
| 97 int len = GetNextRangeLen(); | 102 int64 len = GetNextRangeLen(); |
| 98 if (!len) | 103 if (!len) |
| 99 return 0; | 104 return 0; |
| 100 | 105 |
| 101 DVLOG(3) << "ShouldValidateCache len: " << len; | 106 DVLOG(3) << "ShouldValidateCache len: " << len; |
| 102 | 107 |
| 103 if (sparse_entry_) { | 108 if (sparse_entry_) { |
| 104 DCHECK(callback_.is_null()); | 109 DCHECK(callback_.is_null()); |
| 105 int64* start = new int64; | 110 int64* start = new int64; |
| 111 // TODO(asanka): Use the full len when int64s are plumbed all the way | |
| 112 // through. | |
| 113 int cached_len = std::min<int64>(std::numeric_limits<int32>::max(), len); | |
| 114 | |
| 106 // This callback now owns "start". We make sure to keep it | 115 // This callback now owns "start". We make sure to keep it |
| 107 // in a local variable since we want to use it later. | 116 // in a local variable since we want to use it later. |
| 108 CompletionCallback cb = | 117 CompletionCallback cb = |
| 109 base::Bind(&PartialData::GetAvailableRangeCompleted, | 118 base::Bind(&PartialData::GetAvailableRangeCompleted, |
| 110 weak_factory_.GetWeakPtr(), base::Owned(start)); | 119 weak_factory_.GetWeakPtr(), base::Owned(start)); |
| 111 cached_min_len_ = | 120 cached_min_len_ = |
| 112 entry->GetAvailableRange(current_range_start_, len, start, cb); | 121 entry->GetAvailableRange(current_range_start_, cached_len, start, cb); |
| 113 | 122 |
| 114 if (cached_min_len_ == ERR_IO_PENDING) { | 123 if (cached_min_len_ == ERR_IO_PENDING) { |
| 115 callback_ = callback; | 124 callback_ = callback; |
| 116 return ERR_IO_PENDING; | 125 return ERR_IO_PENDING; |
| 117 } else { | 126 } else { |
| 118 cached_start_ = *start; | 127 cached_start_ = *start; |
| 119 } | 128 } |
| 120 } else if (!truncated_) { | 129 } else if (!truncated_) { |
| 121 if (byte_range_.HasFirstBytePosition() && | 130 if (byte_range_.HasFirstBytePosition() && |
| 122 byte_range_.first_byte_position() >= resource_size_) { | 131 byte_range_.first_byte_position() >= resource_size_) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 133 | 142 |
| 134 // Return a positive number to indicate success (versus error or finished). | 143 // Return a positive number to indicate success (versus error or finished). |
| 135 return 1; | 144 return 1; |
| 136 } | 145 } |
| 137 | 146 |
| 138 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry, | 147 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry, |
| 139 HttpRequestHeaders* headers) { | 148 HttpRequestHeaders* headers) { |
| 140 DCHECK_GE(current_range_start_, 0); | 149 DCHECK_GE(current_range_start_, 0); |
| 141 DCHECK_GE(cached_min_len_, 0); | 150 DCHECK_GE(cached_min_len_, 0); |
| 142 | 151 |
| 143 int len = GetNextRangeLen(); | 152 int64 len = GetNextRangeLen(); |
| 153 // PrepareCacheValidation shouldn't have been called if ShouldValidateCache() | |
| 154 // returned 0. | |
| 144 DCHECK_NE(0, len); | 155 DCHECK_NE(0, len); |
| 145 range_present_ = false; | 156 range_present_ = false; |
| 146 | 157 |
| 147 headers->CopyFrom(extra_headers_); | 158 headers->CopyFrom(extra_headers_); |
| 148 | 159 |
| 160 // Do we need to request the remainder from the network? If so just issue an | |
| 161 // open ended range request. | |
| 162 if (len == kUnbounded) { | |
| 163 DCHECK_EQ(0, cached_min_len_); // Nothing else should be stored. All cached | |
| 164 // ranges are finite, so we don't expect len | |
| 165 // to be kUnbounded. | |
| 166 cached_start_ = 0; | |
| 167 current_range_end_ = -1; | |
| 168 final_range_ = true; | |
| 169 headers->SetHeader( | |
| 170 HttpRequestHeaders::kRange, | |
| 171 HttpByteRange::RightUnbounded(current_range_start_).GetHeaderValue()); | |
| 172 return; | |
| 173 } | |
| 174 | |
| 149 if (!cached_min_len_) { | 175 if (!cached_min_len_) { |
| 150 // We don't have anything else stored. | 176 // We don't have anything else stored. |
| 151 final_range_ = true; | 177 final_range_ = true; |
| 152 cached_start_ = | 178 cached_start_ = |
| 153 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; | 179 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; |
| 154 } | 180 } |
| 155 | 181 |
| 156 if (current_range_start_ == cached_start_) { | 182 if (current_range_start_ == cached_start_) { |
| 157 // The data lives in the cache. | 183 // The data lives in the cache. |
| 158 range_present_ = true; | 184 range_present_ = true; |
| 159 current_range_end_ = cached_start_ + cached_min_len_ - 1; | 185 current_range_end_ = cached_start_ + cached_min_len_ - 1; |
| 160 if (len == cached_min_len_) | 186 if (len == cached_min_len_) |
| 161 final_range_ = true; | 187 final_range_ = true; |
| 162 } else { | 188 } else { |
| 163 // This range is not in the cache. | 189 // This range is not in the cache. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 void PartialData::FixContentLength(HttpResponseHeaders* headers) { | 384 void PartialData::FixContentLength(HttpResponseHeaders* headers) { |
| 359 headers->RemoveHeader(kLengthHeader); | 385 headers->RemoveHeader(kLengthHeader); |
| 360 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, | 386 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, |
| 361 resource_size_)); | 387 resource_size_)); |
| 362 } | 388 } |
| 363 | 389 |
| 364 int PartialData::CacheRead(disk_cache::Entry* entry, | 390 int PartialData::CacheRead(disk_cache::Entry* entry, |
| 365 IOBuffer* data, | 391 IOBuffer* data, |
| 366 int data_len, | 392 int data_len, |
| 367 const CompletionCallback& callback) { | 393 const CompletionCallback& callback) { |
| 368 int read_len = std::min(data_len, cached_min_len_); | 394 int read_len = std::min<int64>(data_len, cached_min_len_); |
| 369 if (!read_len) | 395 if (!read_len) |
| 370 return 0; | 396 return 0; |
| 371 | 397 |
| 372 int rv = 0; | 398 int rv = 0; |
| 373 if (sparse_entry_) { | 399 if (sparse_entry_) { |
| 374 rv = entry->ReadSparseData(current_range_start_, data, read_len, | 400 rv = entry->ReadSparseData(current_range_start_, data, read_len, |
| 375 callback); | 401 callback); |
| 376 } else { | 402 } else { |
| 377 if (current_range_start_ > kint32max) | 403 if (current_range_start_ > kint32max) |
| 378 return ERR_INVALID_ARGUMENT; | 404 return ERR_INVALID_ARGUMENT; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 407 cached_min_len_ -= result; | 433 cached_min_len_ -= result; |
| 408 DCHECK_GE(cached_min_len_, 0); | 434 DCHECK_GE(cached_min_len_, 0); |
| 409 } | 435 } |
| 410 } | 436 } |
| 411 | 437 |
| 412 void PartialData::OnNetworkReadCompleted(int result) { | 438 void PartialData::OnNetworkReadCompleted(int result) { |
| 413 if (result > 0) | 439 if (result > 0) |
| 414 current_range_start_ += result; | 440 current_range_start_ += result; |
| 415 } | 441 } |
| 416 | 442 |
| 417 int PartialData::GetNextRangeLen() { | 443 int64 PartialData::GetNextRangeLen() { |
| 418 int64 range_len = | 444 return byte_range_.HasLastBytePosition() |
|
rvargas (doing something else)
2015/07/27 22:25:12
It seems like we should eliminate this method.
asanka
2015/08/18 22:46:59
New patchset adds another call site. Let me know i
rvargas (doing something else)
2015/08/19 23:46:37
The reason was that the code at the call sites wou
asanka
2015/09/04 19:09:03
SG. Removed. I think it also makes the handling of
| |
| 419 byte_range_.HasLastBytePosition() ? | 445 ? byte_range_.last_byte_position() - current_range_start_ + 1 |
| 420 byte_range_.last_byte_position() - current_range_start_ + 1 : | 446 : kUnbounded; |
| 421 kint32max; | |
| 422 if (range_len > kint32max) | |
| 423 range_len = kint32max; | |
| 424 return static_cast<int32>(range_len); | |
| 425 } | 447 } |
| 426 | 448 |
| 427 void PartialData::GetAvailableRangeCompleted(int64* start, int result) { | 449 void PartialData::GetAvailableRangeCompleted(int64* start, int result) { |
| 428 DCHECK(!callback_.is_null()); | 450 DCHECK(!callback_.is_null()); |
| 429 DCHECK_NE(ERR_IO_PENDING, result); | 451 DCHECK_NE(ERR_IO_PENDING, result); |
| 430 | 452 |
| 431 cached_start_ = *start; | 453 cached_start_ = *start; |
| 432 cached_min_len_ = result; | 454 cached_min_len_ = result; |
| 433 if (result >= 0) | 455 if (result >= 0) |
| 434 result = 1; // Return success, go ahead and validate the entry. | 456 result = 1; // Return success, go ahead and validate the entry. |
| 435 | 457 |
| 436 CompletionCallback cb = callback_; | 458 CompletionCallback cb = callback_; |
| 437 callback_.Reset(); | 459 callback_.Reset(); |
| 438 cb.Run(result); | 460 cb.Run(result); |
| 439 } | 461 } |
| 440 | 462 |
| 441 } // namespace net | 463 } // namespace net |
| OLD | NEW |