// 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/url_request/url_request_simple_job.h"

#include <vector>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request_status.h"

namespace net {

namespace {

void CopyData(const scoped_refptr<IOBuffer>& buf,
              int buf_size,
              const scoped_refptr<base::RefCountedMemory>& data,
              int64 data_offset) {
  memcpy(buf->data(), data->front() + data_offset, buf_size);
}

}  // namespace

URLRequestSimpleJob::URLRequestSimpleJob(URLRequest* request,
                                         NetworkDelegate* network_delegate)
    : URLRangeRequestJob(request, network_delegate),
      next_data_offset_(0),
      task_runner_(base::WorkerPool::GetTaskRunner(false)),
      weak_factory_(this) {
}

void URLRequestSimpleJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&URLRequestSimpleJob::StartAsync, weak_factory_.GetWeakPtr()));
}

void URLRequestSimpleJob::Kill() {
  weak_factory_.InvalidateWeakPtrs();
  URLRangeRequestJob::Kill();
}

bool URLRequestSimpleJob::GetMimeType(std::string* mime_type) const {
  *mime_type = mime_type_;
  return true;
}

bool URLRequestSimpleJob::GetCharset(std::string* charset) {
  *charset = charset_;
  return true;
}

URLRequestSimpleJob::~URLRequestSimpleJob() {}

bool URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size,
                                      int* bytes_read) {
  DCHECK(bytes_read);
  buf_size = static_cast<int>(
      std::min(static_cast<int64>(buf_size),
               byte_range_.last_byte_position() - next_data_offset_ + 1));
  DCHECK_GE(buf_size, 0);
  if (buf_size == 0) {
    *bytes_read = 0;
    return true;
  }

  // Do memory copy on a background thread. See crbug.com/422489.
  GetTaskRunner()->PostTaskAndReply(
      FROM_HERE, base::Bind(&CopyData, make_scoped_refptr(buf), buf_size, data_,
                            next_data_offset_),
      base::Bind(&URLRequestSimpleJob::OnReadCompleted,
                 weak_factory_.GetWeakPtr(), buf_size));
  next_data_offset_ += buf_size;
  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
  return false;
}

void URLRequestSimpleJob::OnReadCompleted(int bytes_read) {
  SetStatus(URLRequestStatus());
  NotifyReadComplete(bytes_read);
}

base::TaskRunner* URLRequestSimpleJob::GetTaskRunner() const {
  return task_runner_.get();
}

int URLRequestSimpleJob::GetData(std::string* mime_type,
                                 std::string* charset,
                                 std::string* data,
                                 const CompletionCallback& callback) const {
  NOTREACHED();
  return ERR_UNEXPECTED;
}

int URLRequestSimpleJob::GetRefCountedData(
    std::string* mime_type,
    std::string* charset,
    scoped_refptr<base::RefCountedMemory>* data,
    const CompletionCallback& callback) const {
  scoped_refptr<base::RefCountedString> str_data(new base::RefCountedString());
  int result = GetData(mime_type, charset, &str_data->data(), callback);
  *data = str_data;
  return result;
}

void URLRequestSimpleJob::StartAsync() {
  if (!request_)
    return;

  if (ranges().size() > 1) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
                                ERR_REQUEST_RANGE_NOT_SATISFIABLE));
    return;
  }

  if (!ranges().empty() && range_parse_result() == OK)
    byte_range_ = ranges().front();

  const int result =
      GetRefCountedData(&mime_type_, &charset_, &data_,
                        base::Bind(&URLRequestSimpleJob::OnGetDataCompleted,
                                   weak_factory_.GetWeakPtr()));

  if (result != ERR_IO_PENDING)
    OnGetDataCompleted(result);
}

void URLRequestSimpleJob::OnGetDataCompleted(int result) {
  if (result == OK) {
    // Notify that the headers are complete
    if (!byte_range_.ComputeBounds(data_->size())) {
      NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
                 ERR_REQUEST_RANGE_NOT_SATISFIABLE));
      return;
    }

    next_data_offset_ = byte_range_.first_byte_position();
    set_expected_content_size(byte_range_.last_byte_position() -
                              next_data_offset_ + 1);
    NotifyHeadersComplete();
  } else {
    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
  }
}

}  // namespace net
