| 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" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 return true; | 67 return true; |
| 66 } | 68 } |
| 67 | 69 |
| 68 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { | 70 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { |
| 69 DCHECK(extra_headers_.IsEmpty()); | 71 DCHECK(extra_headers_.IsEmpty()); |
| 70 extra_headers_.CopyFrom(headers); | 72 extra_headers_.CopyFrom(headers); |
| 71 } | 73 } |
| 72 | 74 |
| 73 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const { | 75 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const { |
| 74 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange()); | 76 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange()); |
| 75 int64 end = byte_range_.IsSuffixByteRange() ? | 77 int64_t end = byte_range_.IsSuffixByteRange() |
| 76 byte_range_.suffix_length() : byte_range_.last_byte_position(); | 78 ? byte_range_.suffix_length() |
| 79 : byte_range_.last_byte_position(); |
| 77 | 80 |
| 78 headers->CopyFrom(extra_headers_); | 81 headers->CopyFrom(extra_headers_); |
| 79 if (truncated_ || !byte_range_.IsValid()) | 82 if (truncated_ || !byte_range_.IsValid()) |
| 80 return; | 83 return; |
| 81 | 84 |
| 82 if (current_range_start_ < 0) { | 85 if (current_range_start_ < 0) { |
| 83 headers->SetHeader(HttpRequestHeaders::kRange, | 86 headers->SetHeader(HttpRequestHeaders::kRange, |
| 84 HttpByteRange::Suffix(end).GetHeaderValue()); | 87 HttpByteRange::Suffix(end).GetHeaderValue()); |
| 85 } else { | 88 } else { |
| 86 headers->SetHeader(HttpRequestHeaders::kRange, | 89 headers->SetHeader(HttpRequestHeaders::kRange, |
| 87 HttpByteRange::Bounded( | 90 HttpByteRange::Bounded( |
| 88 current_range_start_, end).GetHeaderValue()); | 91 current_range_start_, end).GetHeaderValue()); |
| 89 } | 92 } |
| 90 } | 93 } |
| 91 | 94 |
| 92 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, | 95 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, |
| 93 const CompletionCallback& callback) { | 96 const CompletionCallback& callback) { |
| 94 DCHECK_GE(current_range_start_, 0); | 97 DCHECK_GE(current_range_start_, 0); |
| 95 | 98 |
| 96 // Scan the disk cache for the first cached portion within this range. | 99 // Scan the disk cache for the first cached portion within this range. |
| 97 int len = GetNextRangeLen(); | 100 int len = GetNextRangeLen(); |
| 98 if (!len) | 101 if (!len) |
| 99 return 0; | 102 return 0; |
| 100 | 103 |
| 101 DVLOG(3) << "ShouldValidateCache len: " << len; | 104 DVLOG(3) << "ShouldValidateCache len: " << len; |
| 102 | 105 |
| 103 if (sparse_entry_) { | 106 if (sparse_entry_) { |
| 104 DCHECK(callback_.is_null()); | 107 DCHECK(callback_.is_null()); |
| 105 int64* start = new int64; | 108 int64_t* start = new int64_t; |
| 106 // This callback now owns "start". We make sure to keep it | 109 // This callback now owns "start". We make sure to keep it |
| 107 // in a local variable since we want to use it later. | 110 // in a local variable since we want to use it later. |
| 108 CompletionCallback cb = | 111 CompletionCallback cb = |
| 109 base::Bind(&PartialData::GetAvailableRangeCompleted, | 112 base::Bind(&PartialData::GetAvailableRangeCompleted, |
| 110 weak_factory_.GetWeakPtr(), base::Owned(start)); | 113 weak_factory_.GetWeakPtr(), base::Owned(start)); |
| 111 cached_min_len_ = | 114 cached_min_len_ = |
| 112 entry->GetAvailableRange(current_range_start_, len, start, cb); | 115 entry->GetAvailableRange(current_range_start_, len, start, cb); |
| 113 | 116 |
| 114 if (cached_min_len_ == ERR_IO_PENDING) { | 117 if (cached_min_len_ == ERR_IO_PENDING) { |
| 115 callback_ = callback; | 118 callback_ = callback; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 // We don't have the real length and the user may be trying to create a | 189 // We don't have the real length and the user may be trying to create a |
| 187 // sparse entry so let's not write to this entry. | 190 // sparse entry so let's not write to this entry. |
| 188 if (byte_range_.IsValid()) | 191 if (byte_range_.IsValid()) |
| 189 return false; | 192 return false; |
| 190 | 193 |
| 191 if (!headers->HasStrongValidators()) | 194 if (!headers->HasStrongValidators()) |
| 192 return false; | 195 return false; |
| 193 | 196 |
| 194 // Now we avoid resume if there is no content length, but that was not | 197 // Now we avoid resume if there is no content length, but that was not |
| 195 // always the case so double check here. | 198 // always the case so double check here. |
| 196 int64 total_length = headers->GetContentLength(); | 199 int64_t total_length = headers->GetContentLength(); |
| 197 if (total_length <= 0) | 200 if (total_length <= 0) |
| 198 return false; | 201 return false; |
| 199 | 202 |
| 200 truncated_ = true; | 203 truncated_ = true; |
| 201 initial_validation_ = true; | 204 initial_validation_ = true; |
| 202 sparse_entry_ = false; | 205 sparse_entry_ = false; |
| 203 int current_len = entry->GetDataSize(kDataStream); | 206 int current_len = entry->GetDataSize(kDataStream); |
| 204 byte_range_.set_first_byte_position(current_len); | 207 byte_range_.set_first_byte_position(current_len); |
| 205 resource_size_ = total_length; | 208 resource_size_ = total_length; |
| 206 current_range_start_ = current_len; | 209 current_range_start_ = current_len; |
| 207 cached_min_len_ = current_len; | 210 cached_min_len_ = current_len; |
| 208 cached_start_ = current_len + 1; | 211 cached_start_ = current_len + 1; |
| 209 return true; | 212 return true; |
| 210 } | 213 } |
| 211 | 214 |
| 212 if (headers->response_code() != 206) { | 215 if (headers->response_code() != 206) { |
| 213 DCHECK(byte_range_.IsValid()); | 216 DCHECK(byte_range_.IsValid()); |
| 214 sparse_entry_ = false; | 217 sparse_entry_ = false; |
| 215 resource_size_ = entry->GetDataSize(kDataStream); | 218 resource_size_ = entry->GetDataSize(kDataStream); |
| 216 DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_; | 219 DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_; |
| 217 return true; | 220 return true; |
| 218 } | 221 } |
| 219 | 222 |
| 220 if (!headers->HasStrongValidators()) | 223 if (!headers->HasStrongValidators()) |
| 221 return false; | 224 return false; |
| 222 | 225 |
| 223 int64 length_value = headers->GetContentLength(); | 226 int64_t length_value = headers->GetContentLength(); |
| 224 if (length_value <= 0) | 227 if (length_value <= 0) |
| 225 return false; // We must have stored the resource length. | 228 return false; // We must have stored the resource length. |
| 226 | 229 |
| 227 resource_size_ = length_value; | 230 resource_size_ = length_value; |
| 228 | 231 |
| 229 // Make sure that this is really a sparse entry. | 232 // Make sure that this is really a sparse entry. |
| 230 return entry->CouldBeSparse(); | 233 return entry->CouldBeSparse(); |
| 231 } | 234 } |
| 232 | 235 |
| 233 void PartialData::SetRangeToStartDownload() { | 236 void PartialData::SetRangeToStartDownload() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 263 bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) { | 266 bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) { |
| 264 if (headers->response_code() == 304) { | 267 if (headers->response_code() == 304) { |
| 265 if (!byte_range_.IsValid() || truncated_) | 268 if (!byte_range_.IsValid() || truncated_) |
| 266 return true; | 269 return true; |
| 267 | 270 |
| 268 // We must have a complete range here. | 271 // We must have a complete range here. |
| 269 return byte_range_.HasFirstBytePosition() && | 272 return byte_range_.HasFirstBytePosition() && |
| 270 byte_range_.HasLastBytePosition(); | 273 byte_range_.HasLastBytePosition(); |
| 271 } | 274 } |
| 272 | 275 |
| 273 int64 start, end, total_length; | 276 int64_t start, end, total_length; |
| 274 if (!headers->GetContentRange(&start, &end, &total_length)) | 277 if (!headers->GetContentRange(&start, &end, &total_length)) |
| 275 return false; | 278 return false; |
| 276 if (total_length <= 0) | 279 if (total_length <= 0) |
| 277 return false; | 280 return false; |
| 278 | 281 |
| 279 DCHECK_EQ(headers->response_code(), 206); | 282 DCHECK_EQ(headers->response_code(), 206); |
| 280 | 283 |
| 281 // A server should return a valid content length with a 206 (per the standard) | 284 // A server should return a valid content length with a 206 (per the standard) |
| 282 // but relax the requirement because some servers don't do that. | 285 // but relax the requirement because some servers don't do that. |
| 283 int64 content_length = headers->GetContentLength(); | 286 int64_t content_length = headers->GetContentLength(); |
| 284 if (content_length > 0 && content_length != end - start + 1) | 287 if (content_length > 0 && content_length != end - start + 1) |
| 285 return false; | 288 return false; |
| 286 | 289 |
| 287 if (!resource_size_) { | 290 if (!resource_size_) { |
| 288 // First response. Update our values with the ones provided by the server. | 291 // First response. Update our values with the ones provided by the server. |
| 289 resource_size_ = total_length; | 292 resource_size_ = total_length; |
| 290 if (!byte_range_.HasFirstBytePosition()) { | 293 if (!byte_range_.HasFirstBytePosition()) { |
| 291 byte_range_.set_first_byte_position(start); | 294 byte_range_.set_first_byte_position(start); |
| 292 current_range_start_ = start; | 295 current_range_start_ = start; |
| 293 } | 296 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 const CompletionCallback& callback) { | 370 const CompletionCallback& callback) { |
| 368 int read_len = std::min(data_len, cached_min_len_); | 371 int read_len = std::min(data_len, cached_min_len_); |
| 369 if (!read_len) | 372 if (!read_len) |
| 370 return 0; | 373 return 0; |
| 371 | 374 |
| 372 int rv = 0; | 375 int rv = 0; |
| 373 if (sparse_entry_) { | 376 if (sparse_entry_) { |
| 374 rv = entry->ReadSparseData(current_range_start_, data, read_len, | 377 rv = entry->ReadSparseData(current_range_start_, data, read_len, |
| 375 callback); | 378 callback); |
| 376 } else { | 379 } else { |
| 377 if (current_range_start_ > kint32max) | 380 if (current_range_start_ > std::numeric_limits<int32_t>::max()) |
| 378 return ERR_INVALID_ARGUMENT; | 381 return ERR_INVALID_ARGUMENT; |
| 379 | 382 |
| 380 rv = entry->ReadData(kDataStream, static_cast<int>(current_range_start_), | 383 rv = entry->ReadData(kDataStream, static_cast<int>(current_range_start_), |
| 381 data, read_len, callback); | 384 data, read_len, callback); |
| 382 } | 385 } |
| 383 return rv; | 386 return rv; |
| 384 } | 387 } |
| 385 | 388 |
| 386 int PartialData::CacheWrite(disk_cache::Entry* entry, | 389 int PartialData::CacheWrite(disk_cache::Entry* entry, |
| 387 IOBuffer* data, | 390 IOBuffer* data, |
| 388 int data_len, | 391 int data_len, |
| 389 const CompletionCallback& callback) { | 392 const CompletionCallback& callback) { |
| 390 DVLOG(3) << "To write: " << data_len; | 393 DVLOG(3) << "To write: " << data_len; |
| 391 if (sparse_entry_) { | 394 if (sparse_entry_) { |
| 392 return entry->WriteSparseData( | 395 return entry->WriteSparseData( |
| 393 current_range_start_, data, data_len, callback); | 396 current_range_start_, data, data_len, callback); |
| 394 } else { | 397 } else { |
| 395 if (current_range_start_ > kint32max) | 398 if (current_range_start_ > std::numeric_limits<int32_t>::max()) |
| 396 return ERR_INVALID_ARGUMENT; | 399 return ERR_INVALID_ARGUMENT; |
| 397 | 400 |
| 398 return entry->WriteData(kDataStream, static_cast<int>(current_range_start_), | 401 return entry->WriteData(kDataStream, static_cast<int>(current_range_start_), |
| 399 data, data_len, callback, true); | 402 data, data_len, callback, true); |
| 400 } | 403 } |
| 401 } | 404 } |
| 402 | 405 |
| 403 void PartialData::OnCacheReadCompleted(int result) { | 406 void PartialData::OnCacheReadCompleted(int result) { |
| 404 DVLOG(3) << "Read: " << result; | 407 DVLOG(3) << "Read: " << result; |
| 405 if (result > 0) { | 408 if (result > 0) { |
| 406 current_range_start_ += result; | 409 current_range_start_ += result; |
| 407 cached_min_len_ -= result; | 410 cached_min_len_ -= result; |
| 408 DCHECK_GE(cached_min_len_, 0); | 411 DCHECK_GE(cached_min_len_, 0); |
| 409 } | 412 } |
| 410 } | 413 } |
| 411 | 414 |
| 412 void PartialData::OnNetworkReadCompleted(int result) { | 415 void PartialData::OnNetworkReadCompleted(int result) { |
| 413 if (result > 0) | 416 if (result > 0) |
| 414 current_range_start_ += result; | 417 current_range_start_ += result; |
| 415 } | 418 } |
| 416 | 419 |
| 417 int PartialData::GetNextRangeLen() { | 420 int PartialData::GetNextRangeLen() { |
| 418 int64 range_len = | 421 int64_t range_len = |
| 419 byte_range_.HasLastBytePosition() ? | 422 byte_range_.HasLastBytePosition() |
| 420 byte_range_.last_byte_position() - current_range_start_ + 1 : | 423 ? byte_range_.last_byte_position() - current_range_start_ + 1 |
| 421 kint32max; | 424 : std::numeric_limits<int32_t>::max(); |
| 422 if (range_len > kint32max) | 425 if (range_len > std::numeric_limits<int32_t>::max()) |
| 423 range_len = kint32max; | 426 range_len = std::numeric_limits<int32_t>::max(); |
| 424 return static_cast<int32>(range_len); | 427 return static_cast<int32_t>(range_len); |
| 425 } | 428 } |
| 426 | 429 |
| 427 void PartialData::GetAvailableRangeCompleted(int64* start, int result) { | 430 void PartialData::GetAvailableRangeCompleted(int64_t* start, int result) { |
| 428 DCHECK(!callback_.is_null()); | 431 DCHECK(!callback_.is_null()); |
| 429 DCHECK_NE(ERR_IO_PENDING, result); | 432 DCHECK_NE(ERR_IO_PENDING, result); |
| 430 | 433 |
| 431 cached_start_ = *start; | 434 cached_start_ = *start; |
| 432 cached_min_len_ = result; | 435 cached_min_len_ = result; |
| 433 if (result >= 0) | 436 if (result >= 0) |
| 434 result = 1; // Return success, go ahead and validate the entry. | 437 result = 1; // Return success, go ahead and validate the entry. |
| 435 | 438 |
| 436 CompletionCallback cb = callback_; | 439 CompletionCallback cb = callback_; |
| 437 callback_.Reset(); | 440 callback_.Reset(); |
| 438 cb.Run(result); | 441 cb.Run(result); |
| 439 } | 442 } |
| 440 | 443 |
| 441 } // namespace net | 444 } // namespace net |
| OLD | NEW |