OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/http/partial_data.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/string_util.h" |
| 9 #include "net/base/net_errors.h" |
| 10 #include "net/disk_cache/disk_cache.h" |
| 11 #include "net/http/http_util.h" |
| 12 |
| 13 namespace net { |
| 14 |
| 15 bool PartialData::Init(const std::string& headers, |
| 16 const std::string& new_headers) { |
| 17 std::vector<HttpByteRange> ranges; |
| 18 if (!HttpUtil::ParseRanges(headers, &ranges) || ranges.size() != 1) |
| 19 return false; |
| 20 |
| 21 // We can handle this range request. |
| 22 byte_range_ = ranges[0]; |
| 23 if (!byte_range_.IsValid()) |
| 24 return false; |
| 25 |
| 26 extra_headers_ = new_headers; |
| 27 |
| 28 // TODO(rvargas): Handle requests without explicit start or end. |
| 29 DCHECK(byte_range_.HasFirstBytePosition()); |
| 30 current_range_start_ = byte_range_.first_byte_position(); |
| 31 return true; |
| 32 } |
| 33 |
| 34 void PartialData::RestoreHeaders(std::string* headers) const { |
| 35 DCHECK(current_range_start_ >= 0); |
| 36 |
| 37 // TODO(rvargas): Handle requests without explicit start or end. |
| 38 AddRangeHeader(current_range_start_, byte_range_.last_byte_position(), |
| 39 headers); |
| 40 } |
| 41 |
| 42 int PartialData::PrepareCacheValidation(disk_cache::Entry* entry, |
| 43 std::string* headers) { |
| 44 DCHECK(current_range_start_ >= 0); |
| 45 |
| 46 // Scan the disk cache for the first cached portion within this range. |
| 47 int64 range_len = byte_range_.HasLastBytePosition() ? |
| 48 byte_range_.last_byte_position() - current_range_start_ + 1: kint32max; |
| 49 if (range_len > kint32max) |
| 50 range_len = kint32max; |
| 51 int len = static_cast<int32>(range_len); |
| 52 if (!len) |
| 53 return 0; |
| 54 range_present_ = false; |
| 55 |
| 56 cached_min_len_ = entry->GetAvailableRange(current_range_start_, len, |
| 57 &cached_start_); |
| 58 if (cached_min_len_ < 0) { |
| 59 DCHECK(cached_min_len_ != ERR_IO_PENDING); |
| 60 return cached_min_len_; |
| 61 } |
| 62 |
| 63 headers->assign(extra_headers_); |
| 64 |
| 65 if (!cached_min_len_) { |
| 66 // We don't have anything else stored. |
| 67 final_range_ = true; |
| 68 cached_start_ = current_range_start_ + len; |
| 69 } |
| 70 |
| 71 if (current_range_start_ == cached_start_) { |
| 72 // The data lives in the cache. |
| 73 range_present_ = true; |
| 74 if (len == cached_min_len_) |
| 75 final_range_ = true; |
| 76 AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1, |
| 77 headers); |
| 78 } else { |
| 79 // This range is not in the cache. |
| 80 AddRangeHeader(current_range_start_, cached_start_ - 1, headers); |
| 81 } |
| 82 |
| 83 // Return a positive number to indicate success (versus error or finished). |
| 84 return 1; |
| 85 } |
| 86 |
| 87 bool PartialData::IsCurrentRangeCached() const { |
| 88 return range_present_; |
| 89 } |
| 90 |
| 91 bool PartialData::IsLastRange() const { |
| 92 return final_range_; |
| 93 } |
| 94 |
| 95 int PartialData::CacheRead(disk_cache::Entry* entry, IOBuffer* data, |
| 96 int data_len, CompletionCallback* callback) { |
| 97 int read_len = std::min(data_len, cached_min_len_); |
| 98 int rv = entry->ReadSparseData(current_range_start_, data, read_len, |
| 99 callback); |
| 100 return rv; |
| 101 } |
| 102 |
| 103 int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data, |
| 104 int data_len, CompletionCallback* callback) { |
| 105 return entry->WriteSparseData(current_range_start_, data, data_len, |
| 106 callback); |
| 107 } |
| 108 |
| 109 void PartialData::OnCacheReadCompleted(int result) { |
| 110 if (result > 0) { |
| 111 current_range_start_ += result; |
| 112 cached_min_len_ -= result; |
| 113 DCHECK(cached_min_len_ >= 0); |
| 114 } else if (!result) { |
| 115 // TODO(rvargas): we can detect this error and make sure that we are not |
| 116 // in a loop of failure/retry. |
| 117 } |
| 118 } |
| 119 |
| 120 void PartialData::OnNetworkReadCompleted(int result) { |
| 121 if (result > 0) |
| 122 current_range_start_ += result; |
| 123 } |
| 124 |
| 125 // Static. |
| 126 void PartialData::AddRangeHeader(int64 start, int64 end, std::string* headers) { |
| 127 headers->append(StringPrintf("Range: bytes=%lld-%lld\r\n", start, end)); |
| 128 } |
| 129 |
| 130 |
| 131 } // namespace net |
OLD | NEW |