// Copyright 2013 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 "media/blink/buffered_resource_loader.h"

#include "base/bits.h"
#include "base/callback_helpers.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "media/base/media_log.h"
#include "media/blink/cache_util.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"

using blink::WebFrame;
using blink::WebString;
using blink::WebURLError;
using blink::WebURLLoader;
using blink::WebURLLoaderOptions;
using blink::WebURLRequest;
using blink::WebURLResponse;

namespace media {

static const int kHttpOK = 200;
static const int kHttpPartialContent = 206;

// Define the number of bytes in a megabyte.
static const int kMegabyte = 1024 * 1024;

// Minimum capacity of the buffer in forward or backward direction.
//
// 2MB is an arbitrary limit; it just seems to be "good enough" in practice.
static const int kMinBufferCapacity = 2 * kMegabyte;

// Maximum capacity of the buffer in forward or backward direction. This is
// effectively the largest single read the code path can handle.
// 20MB is an arbitrary limit; it just seems to be "good enough" in practice.
static const int kMaxBufferCapacity = 20 * kMegabyte;

// Maximum number of bytes outside the buffer we will wait for in order to
// fulfill a read. If a read starts more than 2MB away from the data we
// currently have in the buffer, we will not wait for buffer to reach the read's
// location and will instead reset the request.
static const int kForwardWaitThreshold = 2 * kMegabyte;

// Computes the suggested backward and forward capacity for the buffer
// if one wants to play at |playback_rate| * the natural playback speed.
// Use a value of 0 for |bitrate| if it is unknown.
static void ComputeTargetBufferWindow(float playback_rate, int bitrate,
                                      int* out_backward_capacity,
                                      int* out_forward_capacity) {
  static const int kDefaultBitrate = 200 * 1024 * 8;  // 200 Kbps.
  static const int kMaxBitrate = 20 * kMegabyte * 8;  // 20 Mbps.
  static const float kMaxPlaybackRate = 25.0;
  static const int kTargetSecondsBufferedAhead = 10;
  static const int kTargetSecondsBufferedBehind = 2;

  // Use a default bit rate if unknown and clamp to prevent overflow.
  if (bitrate <= 0)
    bitrate = kDefaultBitrate;
  bitrate = std::min(bitrate, kMaxBitrate);

  // Only scale the buffer window for playback rates greater than 1.0 in
  // magnitude and clamp to prevent overflow.
  bool backward_playback = false;
  if (playback_rate < 0.0f) {
    backward_playback = true;
    playback_rate *= -1.0f;
  }

  playback_rate = std::max(playback_rate, 1.0f);
  playback_rate = std::min(playback_rate, kMaxPlaybackRate);

  int bytes_per_second = (bitrate / 8.0) * playback_rate;

  // Clamp between kMinBufferCapacity and kMaxBufferCapacity.
  *out_forward_capacity = std::max(
      kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity);
  *out_backward_capacity = std::max(
      kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity);

  *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity);
  *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity);

  if (backward_playback)
    std::swap(*out_forward_capacity, *out_backward_capacity);
}

BufferedResourceLoader::BufferedResourceLoader(
    const GURL& url,
    CORSMode cors_mode,
    int64 first_byte_position,
    int64 last_byte_position,
    DeferStrategy strategy,
    int bitrate,
    float playback_rate,
    MediaLog* media_log)
    : buffer_(kMinBufferCapacity, kMinBufferCapacity),
      loader_failed_(false),
      defer_strategy_(strategy),
      might_be_reused_from_cache_in_future_(true),
      range_supported_(false),
      saved_forward_capacity_(0),
      url_(url),
      cors_mode_(cors_mode),
      first_byte_position_(first_byte_position),
      last_byte_position_(last_byte_position),
      single_origin_(true),
      offset_(0),
      content_length_(kPositionNotSpecified),
      instance_size_(kPositionNotSpecified),
      read_position_(0),
      read_size_(0),
      read_buffer_(NULL),
      first_offset_(0),
      last_offset_(0),
      bitrate_(bitrate),
      playback_rate_(playback_rate),
      media_log_(media_log) {

  // Set the initial capacity of |buffer_| based on |bitrate_| and
  // |playback_rate_|.
  UpdateBufferWindow();
}

BufferedResourceLoader::~BufferedResourceLoader() {}

void BufferedResourceLoader::Start(
    const StartCB& start_cb,
    const LoadingStateChangedCB& loading_cb,
    const ProgressCB& progress_cb,
    WebFrame* frame) {
  // Make sure we have not started.
  DCHECK(start_cb_.is_null());
  DCHECK(loading_cb_.is_null());
  DCHECK(progress_cb_.is_null());
  DCHECK(!start_cb.is_null());
  DCHECK(!loading_cb.is_null());
  DCHECK(!progress_cb.is_null());
  CHECK(frame);

  start_cb_ = start_cb;
  loading_cb_ = loading_cb;
  progress_cb_ = progress_cb;

  if (first_byte_position_ != kPositionNotSpecified) {
    // TODO(hclam): server may not support range request so |offset_| may not
    // equal to |first_byte_position_|.
    offset_ = first_byte_position_;
  }

  // Prepare the request.
  WebURLRequest request(url_);
  // TODO(mkwst): Split this into video/audio.
  request.setRequestContext(WebURLRequest::RequestContextVideo);

  if (IsRangeRequest()) {
    request.setHTTPHeaderField(
        WebString::fromUTF8(net::HttpRequestHeaders::kRange),
        WebString::fromUTF8(net::HttpByteRange::Bounded(
            first_byte_position_, last_byte_position_).GetHeaderValue()));
  }

  frame->setReferrerForRequest(request, blink::WebURL());

  // Disable compression, compression for audio/video doesn't make sense...
  request.setHTTPHeaderField(
      WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding),
      WebString::fromUTF8("identity;q=1, *;q=0"));

  // Check for our test WebURLLoader.
  scoped_ptr<WebURLLoader> loader;
  if (test_loader_) {
    loader = test_loader_.Pass();
  } else {
    WebURLLoaderOptions options;
    if (cors_mode_ == kUnspecified) {
      options.allowCredentials = true;
      options.crossOriginRequestPolicy =
          WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
    } else {
      options.exposeAllResponseHeaders = true;
      // The author header set is empty, no preflight should go ahead.
      options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
      options.crossOriginRequestPolicy =
          WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
      if (cors_mode_ == kUseCredentials)
        options.allowCredentials = true;
    }
    loader.reset(frame->createAssociatedURLLoader(options));
  }

  // Start the resource loading.
  loader->loadAsynchronously(request, this);
  active_loader_.reset(new ActiveLoader(loader.Pass()));
  loading_cb_.Run(kLoading);
}

void BufferedResourceLoader::Stop() {
  // Reset callbacks.
  start_cb_.Reset();
  loading_cb_.Reset();
  progress_cb_.Reset();
  read_cb_.Reset();

  // Cancel and reset any active loaders.
  active_loader_.reset();
}

void BufferedResourceLoader::Read(
    int64 position,
    int read_size,
    uint8* buffer,
    const ReadCB& read_cb) {
  DCHECK(start_cb_.is_null());
  DCHECK(read_cb_.is_null());
  DCHECK(!read_cb.is_null());
  DCHECK(buffer);
  DCHECK_GT(read_size, 0);

  // Save the parameter of reading.
  read_cb_ = read_cb;
  read_position_ = position;
  read_size_ = read_size;
  read_buffer_ = buffer;

  // Reads should immediately fail if the loader also failed.
  if (loader_failed_) {
    DoneRead(kFailed, 0);
    return;
  }

  // If we're attempting to read past the end of the file, return a zero
  // indicating EOF.
  //
  // This can happen with callees that read in fixed-sized amounts for parsing
  // or at the end of chunked 200 responses when we discover the actual length
  // of the file.
  if (instance_size_ != kPositionNotSpecified &&
      instance_size_ <= read_position_) {
    DVLOG(1) << "Appear to have seeked beyond EOS; returning 0.";
    DoneRead(kOk, 0);
    return;
  }

  // Make sure |offset_| and |read_position_| does not differ by a large
  // amount.
  if (read_position_ > offset_ + kint32max ||
      read_position_ < offset_ + kint32min) {
    DoneRead(kCacheMiss, 0);
    return;
  }

  // Make sure |read_size_| is not too large for the buffer to ever be able to
  // fulfill the read request.
  if (read_size_ > kMaxBufferCapacity) {
    DoneRead(kFailed, 0);
    return;
  }

  // Prepare the parameters.
  first_offset_ = read_position_ - offset_;
  last_offset_ = first_offset_ + read_size_;

  // If we can serve the request now, do the actual read.
  if (CanFulfillRead()) {
    ReadInternal();
    UpdateDeferBehavior();
    return;
  }

  // If we expect the read request to be fulfilled later, expand capacity as
  // necessary and disable deferring.
  if (WillFulfillRead()) {
    // Advance offset as much as possible to create additional capacity.
    int advance = std::min(first_offset_, buffer_.forward_bytes());
    bool ret = buffer_.Seek(advance);
    DCHECK(ret);

    offset_ += advance;
    first_offset_ -= advance;
    last_offset_ -= advance;

    // Expand capacity to accomodate a read that extends past the normal
    // capacity.
    //
    // This can happen when reading in a large seek index or when the
    // first byte of a read request falls within kForwardWaitThreshold.
    if (last_offset_ > buffer_.forward_capacity()) {
      saved_forward_capacity_ = buffer_.forward_capacity();
      buffer_.set_forward_capacity(last_offset_);
    }

    // Make sure we stop deferring now that there's additional capacity.
    DCHECK(!ShouldDefer())
        << "Capacity was not adjusted properly to prevent deferring.";
    UpdateDeferBehavior();

    return;
  }

  // Make a callback to report failure.
  DoneRead(kCacheMiss, 0);
}

int64 BufferedResourceLoader::content_length() {
  return content_length_;
}

int64 BufferedResourceLoader::instance_size() {
  return instance_size_;
}

bool BufferedResourceLoader::range_supported() {
  return range_supported_;
}

/////////////////////////////////////////////////////////////////////////////
// blink::WebURLLoaderClient implementation.
void BufferedResourceLoader::willSendRequest(
    WebURLLoader* loader,
    WebURLRequest& newRequest,
    const WebURLResponse& redirectResponse) {

  // The load may have been stopped and |start_cb| is destroyed.
  // In this case we shouldn't do anything.
  if (start_cb_.is_null()) {
    // Set the url in the request to an invalid value (empty url).
    newRequest.setURL(blink::WebURL());
    return;
  }

  // Only allow |single_origin_| if we haven't seen a different origin yet.
  if (single_origin_)
    single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();

  url_ = newRequest.url();
}

void BufferedResourceLoader::didSendData(
    WebURLLoader* loader,
    unsigned long long bytes_sent,
    unsigned long long total_bytes_to_be_sent) {
  NOTIMPLEMENTED();
}

void BufferedResourceLoader::didReceiveResponse(
    WebURLLoader* loader,
    const WebURLResponse& response) {
  DVLOG(1) << "didReceiveResponse: HTTP/"
           << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" :
               response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" :
               response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" :
               "Unknown")
           << " " << response.httpStatusCode();
  DCHECK(active_loader_.get());

  // The loader may have been stopped and |start_cb| is destroyed.
  // In this case we shouldn't do anything.
  if (start_cb_.is_null())
    return;

  uint32 reasons = GetReasonsForUncacheability(response);
  might_be_reused_from_cache_in_future_ = reasons == 0;
  UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons == 0);
  int shift = 0;
  int max_enum = base::bits::Log2Ceiling(kMaxReason);
  while (reasons) {
    DCHECK_LT(shift, max_enum);  // Sanity check.
    if (reasons & 0x1) {
      UMA_HISTOGRAM_ENUMERATION("Media.UncacheableReason",
                                shift,
                                max_enum); // PRESUBMIT_IGNORE_UMA_MAX
    }

    reasons >>= 1;
    ++shift;
  }

  // Expected content length can be |kPositionNotSpecified|, in that case
  // |content_length_| is not specified and this is a streaming response.
  content_length_ = response.expectedContentLength();

  // We make a strong assumption that when we reach here we have either
  // received a response from HTTP/HTTPS protocol or the request was
  // successful (in particular range request). So we only verify the partial
  // response for HTTP and HTTPS protocol.
  if (url_.SchemeIsHTTPOrHTTPS()) {
    bool partial_response = (response.httpStatusCode() == kHttpPartialContent);
    bool ok_response = (response.httpStatusCode() == kHttpOK);

    if (IsRangeRequest()) {
      // Check to see whether the server supports byte ranges.
      std::string accept_ranges =
          response.httpHeaderField("Accept-Ranges").utf8();
      range_supported_ = (accept_ranges.find("bytes") != std::string::npos);

      // If we have verified the partial response and it is correct, we will
      // return kOk. It's also possible for a server to support range requests
      // without advertising "Accept-Ranges: bytes".
      if (partial_response && VerifyPartialResponse(response)) {
        range_supported_ = true;
      } else if (ok_response && first_byte_position_ == 0 &&
                 last_byte_position_ == kPositionNotSpecified) {
        // We accept a 200 response for a Range:0- request, trusting the
        // Accept-Ranges header, because Apache thinks that's a reasonable thing
        // to return.
        instance_size_ = content_length_;
      } else {
        DoneStart(kFailed);
        return;
      }
    } else {
      instance_size_ = content_length_;
      if (response.httpStatusCode() != kHttpOK) {
        // We didn't request a range but server didn't reply with "200 OK".
        DoneStart(kFailed);
        return;
      }
    }

  } else {
    CHECK_EQ(instance_size_, kPositionNotSpecified);
    if (content_length_ != kPositionNotSpecified) {
      if (first_byte_position_ == kPositionNotSpecified)
        instance_size_ = content_length_;
      else if (last_byte_position_ == kPositionNotSpecified)
        instance_size_ = content_length_ + first_byte_position_;
    }
  }

  // Calls with a successful response.
  DoneStart(kOk);
}

void BufferedResourceLoader::didReceiveData(
    WebURLLoader* loader,
    const char* data,
    int data_length,
    int encoded_data_length) {
  DVLOG(1) << "didReceiveData: " << data_length << " bytes";
  DCHECK(active_loader_.get());
  DCHECK_GT(data_length, 0);

  buffer_.Append(reinterpret_cast<const uint8*>(data), data_length);

  // If there is an active read request, try to fulfill the request.
  if (HasPendingRead() && CanFulfillRead())
    ReadInternal();

  // At last see if the buffer is full and we need to defer the downloading.
  UpdateDeferBehavior();

  // Consume excess bytes from our in-memory buffer if necessary.
  if (buffer_.forward_bytes() > buffer_.forward_capacity()) {
    int excess = buffer_.forward_bytes() - buffer_.forward_capacity();
    bool success = buffer_.Seek(excess);
    DCHECK(success);
    offset_ += first_offset_ + excess;
  }

  // Notify latest progress and buffered offset.
  progress_cb_.Run(offset_ + buffer_.forward_bytes() - 1);
  Log();
}

void BufferedResourceLoader::didDownloadData(
    blink::WebURLLoader* loader,
    int dataLength,
    int encoded_data_length) {
  NOTIMPLEMENTED();
}

void BufferedResourceLoader::didReceiveCachedMetadata(
    WebURLLoader* loader,
    const char* data,
    int data_length) {
  NOTIMPLEMENTED();
}

void BufferedResourceLoader::didFinishLoading(
    WebURLLoader* loader,
    double finishTime,
    int64_t total_encoded_data_length) {
  DVLOG(1) << "didFinishLoading";
  DCHECK(active_loader_.get());

  // We're done with the loader.
  active_loader_.reset();
  loading_cb_.Run(kLoadingFinished);

  // If we didn't know the |instance_size_| we do now.
  if (instance_size_ == kPositionNotSpecified) {
    instance_size_ = offset_ + buffer_.forward_bytes();
  }

  // If there is a start callback, run it.
  if (!start_cb_.is_null()) {
    DCHECK(read_cb_.is_null())
        << "Shouldn't have a read callback during start";
    DoneStart(kOk);
    return;
  }

  // Don't leave read callbacks hanging around.
  if (HasPendingRead()) {
    // Try to fulfill with what is in the buffer.
    if (CanFulfillRead())
      ReadInternal();
    else
      DoneRead(kCacheMiss, 0);
  }
}

void BufferedResourceLoader::didFail(
    WebURLLoader* loader,
    const WebURLError& error) {
  DVLOG(1) << "didFail: reason=" << error.reason
           << ", isCancellation=" << error.isCancellation
           << ", domain=" << error.domain.utf8().data()
           << ", localizedDescription="
           << error.localizedDescription.utf8().data();
  DCHECK(active_loader_.get());

  // We don't need to continue loading after failure.
  //
  // Keep it alive until we exit this method so that |error| remains valid.
  scoped_ptr<ActiveLoader> active_loader = active_loader_.Pass();
  loader_failed_ = true;
  loading_cb_.Run(kLoadingFailed);

  // Don't leave start callbacks hanging around.
  if (!start_cb_.is_null()) {
    DCHECK(read_cb_.is_null())
        << "Shouldn't have a read callback during start";
    DoneStart(kFailed);
    return;
  }

  // Don't leave read callbacks hanging around.
  if (HasPendingRead()) {
    DoneRead(kFailed, 0);
  }
}

bool BufferedResourceLoader::HasSingleOrigin() const {
  DCHECK(start_cb_.is_null())
      << "Start() must complete before calling HasSingleOrigin()";
  return single_origin_;
}

bool BufferedResourceLoader::DidPassCORSAccessCheck() const {
  DCHECK(start_cb_.is_null())
      << "Start() must complete before calling DidPassCORSAccessCheck()";
  return !loader_failed_ && cors_mode_ != kUnspecified;
}

void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) {
  if (!might_be_reused_from_cache_in_future_ && strategy == kNeverDefer)
    strategy = kCapacityDefer;
  defer_strategy_ = strategy;
  UpdateDeferBehavior();
}

void BufferedResourceLoader::SetPlaybackRate(float playback_rate) {
  playback_rate_ = playback_rate;

  // This is a pause so don't bother updating the buffer window as we'll likely
  // get unpaused in the future.
  if (playback_rate_ == 0.0)
    return;

  UpdateBufferWindow();
}

void BufferedResourceLoader::SetBitrate(int bitrate) {
  DCHECK(bitrate >= 0);
  bitrate_ = bitrate;
  UpdateBufferWindow();
}

/////////////////////////////////////////////////////////////////////////////
// Helper methods.

void BufferedResourceLoader::UpdateBufferWindow() {
  int backward_capacity;
  int forward_capacity;
  ComputeTargetBufferWindow(
      playback_rate_, bitrate_, &backward_capacity, &forward_capacity);

  // This does not evict data from the buffer if the new capacities are less
  // than the current capacities; the new limits will be enforced after the
  // existing excess buffered data is consumed.
  buffer_.set_backward_capacity(backward_capacity);
  buffer_.set_forward_capacity(forward_capacity);
}

void BufferedResourceLoader::UpdateDeferBehavior() {
  if (!active_loader_)
    return;

  SetDeferred(ShouldDefer());
}

void BufferedResourceLoader::SetDeferred(bool deferred) {
  if (active_loader_->deferred() == deferred)
    return;

  active_loader_->SetDeferred(deferred);
  loading_cb_.Run(deferred ? kLoadingDeferred : kLoading);
}

bool BufferedResourceLoader::ShouldDefer() const {
  switch(defer_strategy_) {
    case kNeverDefer:
      return false;

    case kReadThenDefer:
      DCHECK(read_cb_.is_null() || last_offset_ > buffer_.forward_bytes())
          << "We shouldn't stop deferring if we can fulfill the read";
      return read_cb_.is_null();

    case kCapacityDefer:
      return buffer_.forward_bytes() >= buffer_.forward_capacity();
  }
  NOTREACHED();
  return false;
}

bool BufferedResourceLoader::CanFulfillRead() const {
  // If we are reading too far in the backward direction.
  if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
    return false;

  // If the start offset is too far ahead.
  if (first_offset_ >= buffer_.forward_bytes())
    return false;

  // At the point, we verified that first byte requested is within the buffer.
  // If the request has completed, then just returns with what we have now.
  if (!active_loader_)
    return true;

  // If the resource request is still active, make sure the whole requested
  // range is covered.
  if (last_offset_ > buffer_.forward_bytes())
    return false;

  return true;
}

bool BufferedResourceLoader::WillFulfillRead() const {
  // Trying to read too far behind.
  if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
    return false;

  // Trying to read too far ahead.
  if ((first_offset_ - buffer_.forward_bytes()) >= kForwardWaitThreshold)
    return false;

  // The resource request has completed, there's no way we can fulfill the
  // read request.
  if (!active_loader_)
    return false;

  return true;
}

void BufferedResourceLoader::ReadInternal() {
  // Seek to the first byte requested.
  bool ret = buffer_.Seek(first_offset_);
  DCHECK(ret);

  // Then do the read.
  int read = buffer_.Read(read_buffer_, read_size_);
  offset_ += first_offset_ + read;

  // And report with what we have read.
  DoneRead(kOk, read);
}

int64 BufferedResourceLoader::first_byte_position() const {
  return first_byte_position_;
}

// static
bool BufferedResourceLoader::ParseContentRange(
    const std::string& content_range_str, int64* first_byte_position,
    int64* last_byte_position, int64* instance_size) {
  const std::string kUpThroughBytesUnit = "bytes ";
  if (content_range_str.find(kUpThroughBytesUnit) != 0)
    return false;
  std::string range_spec =
      content_range_str.substr(kUpThroughBytesUnit.length());
  size_t dash_offset = range_spec.find("-");
  size_t slash_offset = range_spec.find("/");

  if (dash_offset == std::string::npos || slash_offset == std::string::npos ||
      slash_offset < dash_offset || slash_offset + 1 == range_spec.length()) {
    return false;
  }
  if (!base::StringToInt64(range_spec.substr(0, dash_offset),
                           first_byte_position) ||
      !base::StringToInt64(range_spec.substr(dash_offset + 1,
                                             slash_offset - dash_offset - 1),
                           last_byte_position)) {
    return false;
  }
  if (slash_offset == range_spec.length() - 2 &&
      range_spec[slash_offset + 1] == '*') {
    *instance_size = kPositionNotSpecified;
  } else {
    if (!base::StringToInt64(range_spec.substr(slash_offset + 1),
                             instance_size)) {
      return false;
    }
  }
  if (*last_byte_position < *first_byte_position ||
      (*instance_size != kPositionNotSpecified &&
       *last_byte_position >= *instance_size)) {
    return false;
  }

  return true;
}

bool BufferedResourceLoader::VerifyPartialResponse(
    const WebURLResponse& response) {
  int64 first_byte_position, last_byte_position, instance_size;
  if (!ParseContentRange(response.httpHeaderField("Content-Range").utf8(),
                         &first_byte_position, &last_byte_position,
                         &instance_size)) {
    return false;
  }

  if (instance_size != kPositionNotSpecified) {
    instance_size_ = instance_size;
  }

  if (first_byte_position_ != kPositionNotSpecified &&
      first_byte_position_ != first_byte_position) {
    return false;
  }

  // TODO(hclam): I should also check |last_byte_position|, but since
  // we will never make such a request that it is ok to leave it unimplemented.
  return true;
}

void BufferedResourceLoader::DoneRead(Status status, int bytes_read) {
  if (saved_forward_capacity_) {
    buffer_.set_forward_capacity(saved_forward_capacity_);
    saved_forward_capacity_ = 0;
  }
  read_position_ = 0;
  read_size_ = 0;
  read_buffer_ = NULL;
  first_offset_ = 0;
  last_offset_ = 0;
  Log();

  base::ResetAndReturn(&read_cb_).Run(status, bytes_read);
}


void BufferedResourceLoader::DoneStart(Status status) {
  base::ResetAndReturn(&start_cb_).Run(status);
}

bool BufferedResourceLoader::IsRangeRequest() const {
  return first_byte_position_ != kPositionNotSpecified;
}

void BufferedResourceLoader::Log() {
  media_log_->AddEvent(
      media_log_->CreateBufferedExtentsChangedEvent(
          offset_ - buffer_.backward_bytes(),
          offset_,
          offset_ + buffer_.forward_bytes()));
}

}  // namespace media
