Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(571)

Unified Diff: net/http/partial_data.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/partial_data.h ('k') | net/http/proxy_client_socket.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/partial_data.cc
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
deleted file mode 100644
index f0615d5ac335b4d42bdbdc8a188d417a07e6733a..0000000000000000000000000000000000000000
--- a/net/http/partial_data.cc
+++ /dev/null
@@ -1,513 +0,0 @@
-// Copyright (c) 2012 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/bind.h"
-#include "base/bind_helpers.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-
-namespace net {
-
-namespace {
-
-// The headers that we have to process.
-const char kLengthHeader[] = "Content-Length";
-const char kRangeHeader[] = "Content-Range";
-const int kDataStream = 1;
-
-} // namespace
-
-// A core object that can be detached from the Partialdata object at destruction
-// so that asynchronous operations cleanup can be performed.
-class PartialData::Core {
- public:
- // Build a new core object. Lifetime management is automatic.
- static Core* CreateCore(PartialData* owner) {
- return new Core(owner);
- }
-
- // Wrapper for Entry::GetAvailableRange. If this method returns ERR_IO_PENDING
- // PartialData::GetAvailableRangeCompleted() will be invoked on the owner
- // object when finished (unless Cancel() is called first).
- int GetAvailableRange(disk_cache::Entry* entry, int64 offset, int len,
- int64* start);
-
- // Cancels a pending operation. It is a mistake to call this method if there
- // is no operation in progress; in fact, there will be no object to do so.
- void Cancel();
-
- private:
- explicit Core(PartialData* owner);
- ~Core();
-
- // Pending io completion routine.
- void OnIOComplete(int result);
-
- PartialData* owner_;
- int64 start_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-PartialData::Core::Core(PartialData* owner)
- : owner_(owner), start_(0) {
- DCHECK(!owner_->core_);
- owner_->core_ = this;
-}
-
-PartialData::Core::~Core() {
- if (owner_)
- owner_->core_ = NULL;
-}
-
-void PartialData::Core::Cancel() {
- DCHECK(owner_);
- owner_ = NULL;
-}
-
-int PartialData::Core::GetAvailableRange(disk_cache::Entry* entry, int64 offset,
- int len, int64* start) {
- int rv = entry->GetAvailableRange(
- offset, len, &start_, base::Bind(&PartialData::Core::OnIOComplete,
- base::Unretained(this)));
- if (rv != net::ERR_IO_PENDING) {
- // The callback will not be invoked. Lets cleanup.
- *start = start_;
- delete this;
- }
- return rv;
-}
-
-void PartialData::Core::OnIOComplete(int result) {
- // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "422516 PartialData::Core::OnIOComplete"));
-
- if (owner_)
- owner_->GetAvailableRangeCompleted(result, start_);
- delete this;
-}
-
-// -----------------------------------------------------------------------------
-
-PartialData::PartialData()
- : current_range_start_(0),
- current_range_end_(0),
- cached_start_(0),
- resource_size_(0),
- cached_min_len_(0),
- range_present_(false),
- final_range_(false),
- sparse_entry_(true),
- truncated_(false),
- initial_validation_(false),
- core_(NULL) {
-}
-
-PartialData::~PartialData() {
- if (core_)
- core_->Cancel();
-}
-
-bool PartialData::Init(const HttpRequestHeaders& headers) {
- std::string range_header;
- if (!headers.GetHeader(HttpRequestHeaders::kRange, &range_header))
- return false;
-
- std::vector<HttpByteRange> ranges;
- if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1)
- return false;
-
- // We can handle this range request.
- byte_range_ = ranges[0];
- if (!byte_range_.IsValid())
- return false;
-
- current_range_start_ = byte_range_.first_byte_position();
-
- DVLOG(1) << "Range start: " << current_range_start_ << " end: " <<
- byte_range_.last_byte_position();
- return true;
-}
-
-void PartialData::SetHeaders(const HttpRequestHeaders& headers) {
- DCHECK(extra_headers_.IsEmpty());
- extra_headers_.CopyFrom(headers);
-}
-
-void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
- DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange());
- int64 end = byte_range_.IsSuffixByteRange() ?
- byte_range_.suffix_length() : byte_range_.last_byte_position();
-
- headers->CopyFrom(extra_headers_);
- if (truncated_ || !byte_range_.IsValid())
- return;
-
- if (current_range_start_ < 0) {
- headers->SetHeader(HttpRequestHeaders::kRange,
- HttpByteRange::Suffix(end).GetHeaderValue());
- } else {
- headers->SetHeader(HttpRequestHeaders::kRange,
- HttpByteRange::Bounded(
- current_range_start_, end).GetHeaderValue());
- }
-}
-
-int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
- const CompletionCallback& callback) {
- DCHECK_GE(current_range_start_, 0);
-
- // Scan the disk cache for the first cached portion within this range.
- int len = GetNextRangeLen();
- if (!len)
- return 0;
-
- DVLOG(3) << "ShouldValidateCache len: " << len;
-
- if (sparse_entry_) {
- DCHECK(callback_.is_null());
- Core* core = Core::CreateCore(this);
- cached_min_len_ = core->GetAvailableRange(entry, current_range_start_, len,
- &cached_start_);
-
- if (cached_min_len_ == ERR_IO_PENDING) {
- callback_ = callback;
- return ERR_IO_PENDING;
- }
- } else if (!truncated_) {
- if (byte_range_.HasFirstBytePosition() &&
- byte_range_.first_byte_position() >= resource_size_) {
- // The caller should take care of this condition because we should have
- // failed IsRequestedRangeOK(), but it's better to be consistent here.
- len = 0;
- }
- cached_min_len_ = len;
- cached_start_ = current_range_start_;
- }
-
- if (cached_min_len_ < 0)
- return cached_min_len_;
-
- // Return a positive number to indicate success (versus error or finished).
- return 1;
-}
-
-void PartialData::PrepareCacheValidation(disk_cache::Entry* entry,
- HttpRequestHeaders* headers) {
- DCHECK_GE(current_range_start_, 0);
- DCHECK_GE(cached_min_len_, 0);
-
- int len = GetNextRangeLen();
- DCHECK_NE(0, len);
- range_present_ = false;
-
- headers->CopyFrom(extra_headers_);
-
- if (!cached_min_len_) {
- // We don't have anything else stored.
- final_range_ = true;
- cached_start_ =
- byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0;
- }
-
- if (current_range_start_ == cached_start_) {
- // The data lives in the cache.
- range_present_ = true;
- current_range_end_ = cached_start_ + cached_min_len_ - 1;
- if (len == cached_min_len_)
- final_range_ = true;
- headers->SetHeader(
- HttpRequestHeaders::kRange,
- HttpByteRange::Bounded(current_range_start_, current_range_end_)
- .GetHeaderValue());
- } else {
- // This range is not in the cache.
- current_range_end_ = cached_start_ - 1;
- headers->SetHeader(
- HttpRequestHeaders::kRange,
- HttpByteRange::Bounded(current_range_start_, current_range_end_)
- .GetHeaderValue());
- }
-}
-
-bool PartialData::IsCurrentRangeCached() const {
- return range_present_;
-}
-
-bool PartialData::IsLastRange() const {
- return final_range_;
-}
-
-bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
- disk_cache::Entry* entry,
- bool truncated) {
- resource_size_ = 0;
- if (truncated) {
- DCHECK_EQ(headers->response_code(), 200);
- // We don't have the real length and the user may be trying to create a
- // sparse entry so let's not write to this entry.
- if (byte_range_.IsValid())
- return false;
-
- if (!headers->HasStrongValidators())
- return false;
-
- // Now we avoid resume if there is no content length, but that was not
- // always the case so double check here.
- int64 total_length = headers->GetContentLength();
- if (total_length <= 0)
- return false;
-
- truncated_ = true;
- initial_validation_ = true;
- sparse_entry_ = false;
- int current_len = entry->GetDataSize(kDataStream);
- byte_range_.set_first_byte_position(current_len);
- resource_size_ = total_length;
- current_range_start_ = current_len;
- cached_min_len_ = current_len;
- cached_start_ = current_len + 1;
- return true;
- }
-
- if (headers->response_code() != 206) {
- DCHECK(byte_range_.IsValid());
- sparse_entry_ = false;
- resource_size_ = entry->GetDataSize(kDataStream);
- DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_;
- return true;
- }
-
- if (!headers->HasStrongValidators())
- return false;
-
- int64 length_value = headers->GetContentLength();
- if (length_value <= 0)
- return false; // We must have stored the resource length.
-
- resource_size_ = length_value;
-
- // Make sure that this is really a sparse entry.
- return entry->CouldBeSparse();
-}
-
-void PartialData::SetRangeToStartDownload() {
- DCHECK(truncated_);
- DCHECK(!sparse_entry_);
- current_range_start_ = 0;
- cached_start_ = 0;
- initial_validation_ = false;
-}
-
-bool PartialData::IsRequestedRangeOK() {
- if (byte_range_.IsValid()) {
- if (!byte_range_.ComputeBounds(resource_size_))
- return false;
- if (truncated_)
- return true;
-
- if (current_range_start_ < 0)
- current_range_start_ = byte_range_.first_byte_position();
- } else {
- // This is not a range request but we have partial data stored.
- current_range_start_ = 0;
- byte_range_.set_last_byte_position(resource_size_ - 1);
- }
-
- bool rv = current_range_start_ >= 0;
- if (!rv)
- current_range_start_ = 0;
-
- return rv;
-}
-
-bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
- if (headers->response_code() == 304) {
- if (!byte_range_.IsValid() || truncated_)
- return true;
-
- // We must have a complete range here.
- return byte_range_.HasFirstBytePosition() &&
- byte_range_.HasLastBytePosition();
- }
-
- int64 start, end, total_length;
- if (!headers->GetContentRange(&start, &end, &total_length))
- return false;
- if (total_length <= 0)
- return false;
-
- DCHECK_EQ(headers->response_code(), 206);
-
- // A server should return a valid content length with a 206 (per the standard)
- // but relax the requirement because some servers don't do that.
- int64 content_length = headers->GetContentLength();
- if (content_length > 0 && content_length != end - start + 1)
- return false;
-
- if (!resource_size_) {
- // First response. Update our values with the ones provided by the server.
- resource_size_ = total_length;
- if (!byte_range_.HasFirstBytePosition()) {
- byte_range_.set_first_byte_position(start);
- current_range_start_ = start;
- }
- if (!byte_range_.HasLastBytePosition())
- byte_range_.set_last_byte_position(end);
- } else if (resource_size_ != total_length) {
- return false;
- }
-
- if (truncated_) {
- if (!byte_range_.HasLastBytePosition())
- byte_range_.set_last_byte_position(end);
- }
-
- if (start != current_range_start_)
- return false;
-
- if (!current_range_end_) {
- // There is nothing in the cache.
- DCHECK(byte_range_.HasLastBytePosition());
- current_range_end_ = byte_range_.last_byte_position();
- if (current_range_end_ >= resource_size_) {
- // We didn't know the real file size, and the server is saying that the
- // requested range goes beyond the size. Fix it.
- current_range_end_ = end;
- byte_range_.set_last_byte_position(end);
- }
- }
-
- // If we received a range, but it's not exactly the range we asked for, avoid
- // trouble and signal an error.
- if (end != current_range_end_)
- return false;
-
- return true;
-}
-
-// We are making multiple requests to complete the range requested by the user.
-// Just assume that everything is fine and say that we are returning what was
-// requested.
-void PartialData::FixResponseHeaders(HttpResponseHeaders* headers,
- bool success) {
- if (truncated_)
- return;
-
- if (byte_range_.IsValid() && success) {
- headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
- return;
- }
-
- headers->RemoveHeader(kLengthHeader);
- headers->RemoveHeader(kRangeHeader);
-
- if (byte_range_.IsValid()) {
- headers->ReplaceStatusLine("HTTP/1.1 416 Requested Range Not Satisfiable");
- headers->AddHeader(base::StringPrintf("%s: bytes 0-0/%" PRId64,
- kRangeHeader, resource_size_));
- headers->AddHeader(base::StringPrintf("%s: 0", kLengthHeader));
- } else {
- // TODO(rvargas): Is it safe to change the protocol version?
- headers->ReplaceStatusLine("HTTP/1.1 200 OK");
- DCHECK_NE(resource_size_, 0);
- headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
- resource_size_));
- }
-}
-
-void PartialData::FixContentLength(HttpResponseHeaders* headers) {
- headers->RemoveHeader(kLengthHeader);
- headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
- resource_size_));
-}
-
-int PartialData::CacheRead(
- disk_cache::Entry* entry, IOBuffer* data, int data_len,
- const net::CompletionCallback& callback) {
- int read_len = std::min(data_len, cached_min_len_);
- if (!read_len)
- return 0;
-
- int rv = 0;
- if (sparse_entry_) {
- rv = entry->ReadSparseData(current_range_start_, data, read_len,
- callback);
- } else {
- if (current_range_start_ > kint32max)
- return ERR_INVALID_ARGUMENT;
-
- rv = entry->ReadData(kDataStream, static_cast<int>(current_range_start_),
- data, read_len, callback);
- }
- return rv;
-}
-
-int PartialData::CacheWrite(
- disk_cache::Entry* entry, IOBuffer* data, int data_len,
- const net::CompletionCallback& callback) {
- DVLOG(3) << "To write: " << data_len;
- if (sparse_entry_) {
- return entry->WriteSparseData(
- current_range_start_, data, data_len, callback);
- } else {
- if (current_range_start_ > kint32max)
- return ERR_INVALID_ARGUMENT;
-
- return entry->WriteData(kDataStream, static_cast<int>(current_range_start_),
- data, data_len, callback, true);
- }
-}
-
-void PartialData::OnCacheReadCompleted(int result) {
- DVLOG(3) << "Read: " << result;
- if (result > 0) {
- current_range_start_ += result;
- cached_min_len_ -= result;
- DCHECK_GE(cached_min_len_, 0);
- }
-}
-
-void PartialData::OnNetworkReadCompleted(int result) {
- if (result > 0)
- current_range_start_ += result;
-}
-
-int PartialData::GetNextRangeLen() {
- int64 range_len =
- byte_range_.HasLastBytePosition() ?
- byte_range_.last_byte_position() - current_range_start_ + 1 :
- kint32max;
- if (range_len > kint32max)
- range_len = kint32max;
- return static_cast<int32>(range_len);
-}
-
-void PartialData::GetAvailableRangeCompleted(int result, int64 start) {
- DCHECK(!callback_.is_null());
- DCHECK_NE(ERR_IO_PENDING, result);
-
- cached_start_ = start;
- cached_min_len_ = result;
- if (result >= 0)
- result = 1; // Return success, go ahead and validate the entry.
-
- CompletionCallback cb = callback_;
- callback_.Reset();
- cb.Run(result);
-}
-
-} // namespace net
« no previous file with comments | « net/http/partial_data.h ('k') | net/http/proxy_client_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698