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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 "422516 PartialData::Core::OnIOComplete")); | 96 "422516 PartialData::Core::OnIOComplete")); |
97 | 97 |
98 if (owner_) | 98 if (owner_) |
99 owner_->GetAvailableRangeCompleted(result, start_); | 99 owner_->GetAvailableRangeCompleted(result, start_); |
100 delete this; | 100 delete this; |
101 } | 101 } |
102 | 102 |
103 // ----------------------------------------------------------------------------- | 103 // ----------------------------------------------------------------------------- |
104 | 104 |
105 PartialData::PartialData() | 105 PartialData::PartialData() |
106 : range_present_(false), | 106 : current_range_start_(0), |
| 107 current_range_end_(0), |
| 108 cached_start_(0), |
| 109 resource_size_(0), |
| 110 cached_min_len_(0), |
| 111 range_present_(false), |
107 final_range_(false), | 112 final_range_(false), |
108 sparse_entry_(true), | 113 sparse_entry_(true), |
109 truncated_(false), | 114 truncated_(false), |
110 initial_validation_(false), | 115 initial_validation_(false), |
111 core_(NULL) { | 116 core_(NULL) { |
112 } | 117 } |
113 | 118 |
114 PartialData::~PartialData() { | 119 PartialData::~PartialData() { |
115 if (core_) | 120 if (core_) |
116 core_->Cancel(); | 121 core_->Cancel(); |
117 } | 122 } |
118 | 123 |
119 bool PartialData::Init(const HttpRequestHeaders& headers) { | 124 bool PartialData::Init(const HttpRequestHeaders& headers) { |
120 std::string range_header; | 125 std::string range_header; |
121 if (!headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) | 126 if (!headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) |
122 return false; | 127 return false; |
123 | 128 |
124 std::vector<HttpByteRange> ranges; | 129 std::vector<HttpByteRange> ranges; |
125 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1) | 130 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1) |
126 return false; | 131 return false; |
127 | 132 |
128 // We can handle this range request. | 133 // We can handle this range request. |
129 byte_range_ = ranges[0]; | 134 byte_range_ = ranges[0]; |
130 if (!byte_range_.IsValid()) | 135 if (!byte_range_.IsValid()) |
131 return false; | 136 return false; |
132 | 137 |
133 resource_size_ = 0; | |
134 current_range_start_ = byte_range_.first_byte_position(); | 138 current_range_start_ = byte_range_.first_byte_position(); |
135 | 139 |
136 DVLOG(1) << "Range start: " << current_range_start_ << " end: " << | 140 DVLOG(1) << "Range start: " << current_range_start_ << " end: " << |
137 byte_range_.last_byte_position(); | 141 byte_range_.last_byte_position(); |
138 return true; | 142 return true; |
139 } | 143 } |
140 | 144 |
141 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { | 145 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { |
142 DCHECK(extra_headers_.IsEmpty()); | 146 DCHECK(extra_headers_.IsEmpty()); |
143 extra_headers_.CopyFrom(headers); | 147 extra_headers_.CopyFrom(headers); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 if (!cached_min_len_) { | 219 if (!cached_min_len_) { |
216 // We don't have anything else stored. | 220 // We don't have anything else stored. |
217 final_range_ = true; | 221 final_range_ = true; |
218 cached_start_ = | 222 cached_start_ = |
219 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; | 223 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; |
220 } | 224 } |
221 | 225 |
222 if (current_range_start_ == cached_start_) { | 226 if (current_range_start_ == cached_start_) { |
223 // The data lives in the cache. | 227 // The data lives in the cache. |
224 range_present_ = true; | 228 range_present_ = true; |
| 229 current_range_end_ = cached_start_ + cached_min_len_ - 1; |
225 if (len == cached_min_len_) | 230 if (len == cached_min_len_) |
226 final_range_ = true; | 231 final_range_ = true; |
227 headers->SetHeader( | 232 headers->SetHeader( |
228 HttpRequestHeaders::kRange, | 233 HttpRequestHeaders::kRange, |
229 net::HttpByteRange::Bounded( | 234 HttpByteRange::Bounded(current_range_start_, current_range_end_) |
230 current_range_start_, | 235 .GetHeaderValue()); |
231 cached_start_ + cached_min_len_ - 1).GetHeaderValue()); | |
232 } else { | 236 } else { |
233 // This range is not in the cache. | 237 // This range is not in the cache. |
| 238 current_range_end_ = cached_start_ - 1; |
234 headers->SetHeader( | 239 headers->SetHeader( |
235 HttpRequestHeaders::kRange, | 240 HttpRequestHeaders::kRange, |
236 net::HttpByteRange::Bounded( | 241 HttpByteRange::Bounded(current_range_start_, current_range_end_) |
237 current_range_start_, cached_start_ - 1).GetHeaderValue()); | 242 .GetHeaderValue()); |
238 } | 243 } |
239 } | 244 } |
240 | 245 |
241 bool PartialData::IsCurrentRangeCached() const { | 246 bool PartialData::IsCurrentRangeCached() const { |
242 return range_present_; | 247 return range_present_; |
243 } | 248 } |
244 | 249 |
245 bool PartialData::IsLastRange() const { | 250 bool PartialData::IsLastRange() const { |
246 return final_range_; | 251 return final_range_; |
247 } | 252 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 } | 284 } |
280 | 285 |
281 if (headers->response_code() != 206) { | 286 if (headers->response_code() != 206) { |
282 DCHECK(byte_range_.IsValid()); | 287 DCHECK(byte_range_.IsValid()); |
283 sparse_entry_ = false; | 288 sparse_entry_ = false; |
284 resource_size_ = entry->GetDataSize(kDataStream); | 289 resource_size_ = entry->GetDataSize(kDataStream); |
285 DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_; | 290 DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_; |
286 return true; | 291 return true; |
287 } | 292 } |
288 | 293 |
| 294 if (!headers->HasStrongValidators()) |
| 295 return false; |
| 296 |
289 int64 length_value = headers->GetContentLength(); | 297 int64 length_value = headers->GetContentLength(); |
290 if (length_value <= 0) | 298 if (length_value <= 0) |
291 return false; // We must have stored the resource length. | 299 return false; // We must have stored the resource length. |
292 | 300 |
293 resource_size_ = length_value; | 301 resource_size_ = length_value; |
294 | 302 |
295 // Make sure that this is really a sparse entry. | 303 // Make sure that this is really a sparse entry. |
296 return entry->CouldBeSparse(); | 304 return entry->CouldBeSparse(); |
297 } | 305 } |
298 | 306 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 372 } |
365 | 373 |
366 if (truncated_) { | 374 if (truncated_) { |
367 if (!byte_range_.HasLastBytePosition()) | 375 if (!byte_range_.HasLastBytePosition()) |
368 byte_range_.set_last_byte_position(end); | 376 byte_range_.set_last_byte_position(end); |
369 } | 377 } |
370 | 378 |
371 if (start != current_range_start_) | 379 if (start != current_range_start_) |
372 return false; | 380 return false; |
373 | 381 |
374 if (byte_range_.IsValid() && end > byte_range_.last_byte_position()) | 382 if (!current_range_end_) { |
| 383 // There is nothing in the cache. |
| 384 DCHECK(byte_range_.HasLastBytePosition()); |
| 385 current_range_end_ = byte_range_.last_byte_position(); |
| 386 if (current_range_end_ >= resource_size_) { |
| 387 // We didn't know the real file size, and the server is saying that the |
| 388 // requested range goes beyond the size. Fix it. |
| 389 current_range_end_ = end; |
| 390 byte_range_.set_last_byte_position(end); |
| 391 } |
| 392 } |
| 393 |
| 394 // If we received a range, but it's not exactly the range we asked for, avoid |
| 395 // trouble and signal an error. |
| 396 if (end != current_range_end_) |
375 return false; | 397 return false; |
376 | 398 |
377 return true; | 399 return true; |
378 } | 400 } |
379 | 401 |
380 // We are making multiple requests to complete the range requested by the user. | 402 // We are making multiple requests to complete the range requested by the user. |
381 // Just assume that everything is fine and say that we are returning what was | 403 // Just assume that everything is fine and say that we are returning what was |
382 // requested. | 404 // requested. |
383 void PartialData::FixResponseHeaders(HttpResponseHeaders* headers, | 405 void PartialData::FixResponseHeaders(HttpResponseHeaders* headers, |
384 bool success) { | 406 bool success) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 cached_min_len_ = result; | 504 cached_min_len_ = result; |
483 if (result >= 0) | 505 if (result >= 0) |
484 result = 1; // Return success, go ahead and validate the entry. | 506 result = 1; // Return success, go ahead and validate the entry. |
485 | 507 |
486 CompletionCallback cb = callback_; | 508 CompletionCallback cb = callback_; |
487 callback_.Reset(); | 509 callback_.Reset(); |
488 cb.Run(result); | 510 cb.Run(result); |
489 } | 511 } |
490 | 512 |
491 } // namespace net | 513 } // namespace net |
OLD | NEW |