Index: net/http/partial_data.cc |
=================================================================== |
--- net/http/partial_data.cc (revision 0) |
+++ net/http/partial_data.cc (revision 0) |
@@ -0,0 +1,131 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/http/partial_data.h" |
+ |
+#include "base/logging.h" |
+#include "base/string_util.h" |
+#include "net/base/net_errors.h" |
+#include "net/disk_cache/disk_cache.h" |
+#include "net/http/http_util.h" |
+ |
+namespace net { |
+ |
+bool PartialData::Init(const std::string& headers, |
+ const std::string& new_headers) { |
+ std::vector<HttpByteRange> ranges; |
+ if (!HttpUtil::ParseRanges(headers, &ranges) || ranges.size() != 1) |
+ return false; |
+ |
+ // We can handle this range request. |
+ byte_range_ = ranges[0]; |
+ if (!byte_range_.IsValid()) |
+ return false; |
+ |
+ extra_headers_ = new_headers; |
+ |
+ // TODO(rvargas): Handle requests without explicit start or end. |
+ DCHECK(byte_range_.HasFirstBytePosition()); |
+ current_range_start_ = byte_range_.first_byte_position(); |
+ return true; |
+} |
+ |
+void PartialData::RestoreHeaders(std::string* headers) const { |
+ DCHECK(current_range_start_ >= 0); |
+ |
+ // TODO(rvargas): Handle requests without explicit start or end. |
+ AddRangeHeader(current_range_start_, byte_range_.last_byte_position(), |
+ headers); |
+} |
+ |
+int PartialData::PrepareCacheValidation(disk_cache::Entry* entry, |
+ std::string* headers) { |
+ DCHECK(current_range_start_ >= 0); |
+ |
+ // Scan the disk cache for the first cached portion within this range. |
+ int64 range_len = byte_range_.HasLastBytePosition() ? |
+ byte_range_.last_byte_position() - current_range_start_ + 1: kint32max; |
+ if (range_len > kint32max) |
+ range_len = kint32max; |
+ int len = static_cast<int32>(range_len); |
+ if (!len) |
+ return 0; |
+ range_present_ = false; |
+ |
+ cached_min_len_ = entry->GetAvailableRange(current_range_start_, len, |
+ &cached_start_); |
+ if (cached_min_len_ < 0) { |
+ DCHECK(cached_min_len_ != ERR_IO_PENDING); |
+ return cached_min_len_; |
+ } |
+ |
+ headers->assign(extra_headers_); |
+ |
+ if (!cached_min_len_) { |
+ // We don't have anything else stored. |
+ final_range_ = true; |
+ cached_start_ = current_range_start_ + len; |
+ } |
+ |
+ if (current_range_start_ == cached_start_) { |
+ // The data lives in the cache. |
+ range_present_ = true; |
+ if (len == cached_min_len_) |
+ final_range_ = true; |
+ AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1, |
+ headers); |
+ } else { |
+ // This range is not in the cache. |
+ AddRangeHeader(current_range_start_, cached_start_ - 1, headers); |
+ } |
+ |
+ // Return a positive number to indicate success (versus error or finished). |
+ return 1; |
+} |
+ |
+bool PartialData::IsCurrentRangeCached() const { |
+ return range_present_; |
+} |
+ |
+bool PartialData::IsLastRange() const { |
+ return final_range_; |
+} |
+ |
+int PartialData::CacheRead(disk_cache::Entry* entry, IOBuffer* data, |
+ int data_len, CompletionCallback* callback) { |
+ int read_len = std::min(data_len, cached_min_len_); |
+ int rv = entry->ReadSparseData(current_range_start_, data, read_len, |
+ callback); |
+ return rv; |
+} |
+ |
+int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data, |
+ int data_len, CompletionCallback* callback) { |
+ return entry->WriteSparseData(current_range_start_, data, data_len, |
+ callback); |
+} |
+ |
+void PartialData::OnCacheReadCompleted(int result) { |
+ if (result > 0) { |
+ current_range_start_ += result; |
+ cached_min_len_ -= result; |
+ DCHECK(cached_min_len_ >= 0); |
+ } else if (!result) { |
+ // TODO(rvargas): we can detect this error and make sure that we are not |
+ // in a loop of failure/retry. |
+ } |
+} |
+ |
+void PartialData::OnNetworkReadCompleted(int result) { |
+ if (result > 0) |
+ current_range_start_ += result; |
+} |
+ |
+// Static. |
+void PartialData::AddRangeHeader(int64 start, int64 end, std::string* headers) { |
+ headers->append(StringPrintf("Range: bytes=%lld-%lld\r\n", start, end)); |
+} |
+ |
+ |
+} // namespace net |
Property changes on: net\http\partial_data.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |