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 |