// 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
