// 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 "google_apis/drive/base_requests.h"

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <utility>

#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/request_sender.h"
#include "google_apis/drive/request_util.h"
#include "google_apis/drive/task_util.h"
#include "google_apis/drive/time_util.h"
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
#include "net/http/http_util.h"

namespace {

// Template for optional OAuth2 authorization HTTP header.
const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
// Template for GData API version HTTP header.
const char kGDataVersionHeader[] = "GData-Version: 3.0";

// Maximum number of attempts for re-authentication per request.
const int kMaxReAuthenticateAttemptsPerRequest = 1;

// Template for initiate upload of both GData WAPI and Drive API v2.
const char kUploadContentType[] = "X-Upload-Content-Type: ";
const char kUploadContentLength[] = "X-Upload-Content-Length: ";
const char kUploadResponseLocation[] = "location";

// Template for upload data range of both GData WAPI and Drive API v2.
const char kUploadContentRange[] = "Content-Range: bytes ";
const char kUploadResponseRange[] = "range";

// Mime type of JSON.
const char kJsonMimeType[] = "application/json";

// Mime type of multipart related.
const char kMultipartRelatedMimeTypePrefix[] =
    "multipart/related; boundary=";

// Mime type of multipart mixed.
const char kMultipartMixedMimeTypePrefix[] =
    "multipart/mixed; boundary=";

// Header for each item in a multipart message.
const char kMultipartItemHeaderFormat[] = "--%s\nContent-Type: %s\n\n";

// Footer for whole multipart message.
const char kMultipartFooterFormat[] = "--%s--";

// Parses JSON passed in |json| on |blocking_task_runner|. Runs |callback| on
// the calling thread when finished with either success or failure.
// The callback must not be null.
void ParseJsonOnBlockingPool(
    base::TaskRunner* blocking_task_runner,
    std::string json,
    base::OnceCallback<void(std::unique_ptr<base::Value> value)> callback) {
  base::PostTaskAndReplyWithResult(
      blocking_task_runner, FROM_HERE,
      base::BindOnce(&google_apis::ParseJson, std::move(json)),
      std::move(callback));
}

// Returns response headers as a string. Returns a warning message if
// |response_head| does not contain a valid response. Used only for debugging.
std::string GetResponseHeadersAsString(
    const network::ResourceResponseHead& response_head) {
  // Check that response code indicates response headers are valid (i.e. not
  // malformed) before we retrieve the headers.
  if (response_head.headers->response_code() == -1)
    return "Response headers are malformed!!";

  return response_head.headers->raw_headers();
}

// Obtains the multipart body for the metadata string and file contents. If
// predetermined_boundary is empty, the function generates the boundary string.
bool GetMultipartContent(const std::string& predetermined_boundary,
                         const std::string& metadata_json,
                         const std::string& content_type,
                         const base::FilePath& path,
                         std::string* upload_content_type,
                         std::string* upload_content_data) {
  std::vector<google_apis::ContentTypeAndData> parts(2);
  parts[0].type = kJsonMimeType;
  parts[0].data = metadata_json;
  parts[1].type = content_type;
  if (!ReadFileToString(path, &parts[1].data))
    return false;

  google_apis::ContentTypeAndData output;
  GenerateMultipartBody(google_apis::MULTIPART_RELATED, predetermined_boundary,
                        parts, &output, nullptr);
  upload_content_type->swap(output.type);
  upload_content_data->swap(output.data);
  return true;
}

// Parses JSON body and returns corresponding DriveApiErrorCode if it is found.
// The server may return detailed error status in JSON.
// See https://developers.google.com/drive/handle-errors
google_apis::DriveApiErrorCode MapJsonError(
    google_apis::DriveApiErrorCode code,
    const std::string& error_body) {
  if (IsSuccessfulDriveApiErrorCode(code))
    return code;

  DVLOG(1) << error_body;
  const char kErrorKey[] = "error";
  const char kErrorErrorsKey[] = "errors";
  const char kErrorReasonKey[] = "reason";
  const char kErrorMessageKey[] = "message";
  const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded";
  const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded";
  const char kErrorReasonQuotaExceeded[] = "quotaExceeded";
  const char kErrorReasonResponseTooLarge[] = "responseTooLarge";

  std::unique_ptr<const base::Value> value(google_apis::ParseJson(error_body));
  const base::DictionaryValue* dictionary = NULL;
  const base::DictionaryValue* error = NULL;
  if (value &&
      value->GetAsDictionary(&dictionary) &&
      dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
    // Get error message.
    std::string message;
    error->GetStringWithoutPathExpansion(kErrorMessageKey, &message);
    DLOG(ERROR) << "code: " << code << ", message: " << message;

    // Override the error code based on the reason of the first error.
    const base::ListValue* errors = NULL;
    const base::DictionaryValue* first_error = NULL;
    if (error->GetListWithoutPathExpansion(kErrorErrorsKey, &errors) &&
        errors->GetDictionary(0, &first_error)) {
      std::string reason;
      first_error->GetStringWithoutPathExpansion(kErrorReasonKey, &reason);
      if (reason == kErrorReasonRateLimitExceeded ||
          reason == kErrorReasonUserRateLimitExceeded) {
        return google_apis::HTTP_SERVICE_UNAVAILABLE;
      }
      if (reason == kErrorReasonQuotaExceeded)
        return google_apis::DRIVE_NO_SPACE;
      if (reason == kErrorReasonResponseTooLarge)
        return google_apis::DRIVE_RESPONSE_TOO_LARGE;
    }
  }

  return code;
}

// Used to release (and close) a file on a blocking task.
void CloseFile(base::File file) {}

}  // namespace

namespace google_apis {

std::unique_ptr<base::Value> ParseJson(const std::string& json) {
  int error_code = -1;
  std::string error_message;
  std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
      json, base::JSON_PARSE_RFC, &error_code, &error_message);

  if (!value.get()) {
    std::string trimmed_json;
    if (json.size() < 80) {
      trimmed_json  = json;
    } else {
      // Take the first 50 and the last 10 bytes.
      trimmed_json =
          base::StringPrintf("%s [%s bytes] %s", json.substr(0, 50).c_str(),
                             base::NumberToString(json.size() - 60).c_str(),
                             json.substr(json.size() - 10).c_str());
    }
    LOG(WARNING) << "Error while parsing entry response: " << error_message
                 << ", code: " << error_code << ", json:\n" << trimmed_json;
  }
  return value;
}

void GenerateMultipartBody(MultipartType multipart_type,
                           const std::string& predetermined_boundary,
                           const std::vector<ContentTypeAndData>& parts,
                           ContentTypeAndData* output,
                           std::vector<uint64_t>* data_offset) {
  std::string boundary;
  // Generate random boundary.
  if (predetermined_boundary.empty()) {
    while (true) {
      boundary = net::GenerateMimeMultipartBoundary();
      bool conflict_with_content = false;
      for (auto& part : parts) {
        if (part.data.find(boundary, 0) != std::string::npos) {
          conflict_with_content = true;
          break;
        }
      }
      if (!conflict_with_content)
        break;
    }
  } else {
    boundary = predetermined_boundary;
  }

  switch (multipart_type) {
    case MULTIPART_RELATED:
      output->type = kMultipartRelatedMimeTypePrefix + boundary;
      break;
    case MULTIPART_MIXED:
      output->type = kMultipartMixedMimeTypePrefix + boundary;
      break;
  }

  output->data.clear();
  if (data_offset)
    data_offset->clear();
  for (auto& part : parts) {
    output->data.append(base::StringPrintf(
        kMultipartItemHeaderFormat, boundary.c_str(), part.type.c_str()));
    if (data_offset)
      data_offset->push_back(output->data.size());
    output->data.append(part.data);
    output->data.append("\n");
  }
  output->data.append(
      base::StringPrintf(kMultipartFooterFormat, boundary.c_str()));
}

//============================ UrlFetchRequestBase ===========================

UrlFetchRequestBase::UrlFetchRequestBase(
    RequestSender* sender,
    const ProgressCallback& upload_progress_callback,
    const ProgressCallback& download_progress_callback)
    : re_authenticate_count_(0),
      sender_(sender),
      upload_progress_callback_(upload_progress_callback),
      download_progress_callback_(download_progress_callback),
      response_content_length_(-1),
      weak_ptr_factory_(this) {}

UrlFetchRequestBase::~UrlFetchRequestBase() {}

void UrlFetchRequestBase::Start(const std::string& access_token,
                                const std::string& custom_user_agent,
                                const ReAuthenticateCallback& callback) {
  DCHECK(CalledOnValidThread());
  DCHECK(!access_token.empty());
  DCHECK(!callback.is_null());
  DCHECK(re_authenticate_callback_.is_null());
  Prepare(base::Bind(&UrlFetchRequestBase::StartAfterPrepare,
                     weak_ptr_factory_.GetWeakPtr(), access_token,
                     custom_user_agent, callback));
}

void UrlFetchRequestBase::Prepare(const PrepareCallback& callback) {
  DCHECK(CalledOnValidThread());
  DCHECK(!callback.is_null());
  callback.Run(HTTP_SUCCESS);
}

void UrlFetchRequestBase::StartAfterPrepare(
    const std::string& access_token,
    const std::string& custom_user_agent,
    const ReAuthenticateCallback& callback,
    DriveApiErrorCode code) {
  DCHECK(CalledOnValidThread());
  DCHECK(!access_token.empty());
  DCHECK(!callback.is_null());
  DCHECK(re_authenticate_callback_.is_null());

  const GURL url = GetURL();
  DriveApiErrorCode error_code;
  if (IsSuccessfulDriveApiErrorCode(code))
    error_code = code;
  else if (url.is_empty())
    error_code = DRIVE_OTHER_ERROR;
  else
    error_code = HTTP_SUCCESS;

  if (error_code != HTTP_SUCCESS) {
    // Error is found on generating the url or preparing the request. Send the
    // error message to the callback, and then return immediately without trying
    // to connect to the server.  We need to call CompleteRequestWithError
    // asynchronously because client code does not assume result callback is
    // called synchronously.
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&UrlFetchRequestBase::CompleteRequestWithError,
                              weak_ptr_factory_.GetWeakPtr(), error_code));
    return;
  }

  re_authenticate_callback_ = callback;
  DVLOG(1) << "URL: " << url.spec();

  auto request = std::make_unique<network::ResourceRequest>();
  request->url = url;
  request->method = GetRequestType();
  request->load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
                        net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE;

  // Add request headers.
  // Note that SetHeader clears the current headers and sets it to the passed-in
  // headers, so calling it for each header will result in only the last header
  // being set in request headers.
  if (!custom_user_agent.empty())
    request->headers.SetHeader("User-Agent", custom_user_agent);
  request->headers.AddHeaderFromString(kGDataVersionHeader);
  request->headers.AddHeaderFromString(
      base::StringPrintf(kAuthorizationHeaderFormat, access_token.data()));
  for (const auto& header : GetExtraRequestHeaders()) {
    request->headers.AddHeaderFromString(header);
    DVLOG(1) << "Extra header: " << header;
  }

  url_loader_ = network::SimpleURLLoader::Create(
      std::move(request), sender_->get_traffic_annotation_tag());
  url_loader_->SetAllowHttpErrorResults(true /* allow */);

  download_data_ = std::make_unique<DownloadData>(blocking_task_runner());
  GetOutputFilePath(&download_data_->output_file_path,
                    &download_data_->get_content_callback);
  if (!download_data_->get_content_callback.is_null()) {
    download_data_->get_content_callback =
        CreateRelayCallback(download_data_->get_content_callback);
  }

  // Set upload data if available.
  std::string upload_content_type;
  std::string upload_content;
  if (GetContentData(&upload_content_type, &upload_content)) {
    url_loader_->AttachStringForUpload(upload_content, upload_content_type);
  } else {
    base::FilePath local_file_path;
    int64_t range_offset = 0;
    int64_t range_length = 0;
    if (GetContentFile(&local_file_path, &range_offset, &range_length,
                       &upload_content_type)) {
      url_loader_->AttachFileForUpload(local_file_path, upload_content_type,
                                       range_offset, range_length);
    }
  }

  if (!upload_progress_callback_.is_null()) {
    url_loader_->SetOnUploadProgressCallback(base::BindRepeating(
        &UrlFetchRequestBase::OnUploadProgress, weak_ptr_factory_.GetWeakPtr(),
        upload_progress_callback_));
  }
  if (!download_progress_callback_.is_null()) {
    url_loader_->SetOnDownloadProgressCallback(base::BindRepeating(
        &UrlFetchRequestBase::OnDownloadProgress,
        weak_ptr_factory_.GetWeakPtr(), download_progress_callback_));
  }

  url_loader_->SetOnResponseStartedCallback(base::BindOnce(
      &UrlFetchRequestBase::OnResponseStarted, weak_ptr_factory_.GetWeakPtr()));

  url_loader_->DownloadAsStream(sender_->url_loader_factory(), this);
}

void UrlFetchRequestBase::OnDownloadProgress(
    const ProgressCallback& progress_callback,
    uint64_t current) {
  progress_callback.Run(static_cast<int64_t>(current),
                        response_content_length_);
}

void UrlFetchRequestBase::OnUploadProgress(
    const ProgressCallback& progress_callback,
    uint64_t position,
    uint64_t total) {
  progress_callback.Run(static_cast<int64_t>(position),
                        static_cast<int64_t>(total));
}

void UrlFetchRequestBase::OnResponseStarted(
    const GURL& final_url,
    const network::ResourceResponseHead& response_head) {
  DVLOG(1) << "Response headers:\n"
           << GetResponseHeadersAsString(response_head);
  response_content_length_ = response_head.content_length;
}

// static
bool UrlFetchRequestBase::WriteFileData(base::StringPiece string_piece,
                                        DownloadData* download_data) {
  if (!download_data->output_file.IsValid()) {
    download_data->output_file.Initialize(
        download_data->output_file_path,
        base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
    if (!download_data->output_file.IsValid())
      return false;
  }
  if (download_data->output_file.WriteAtCurrentPos(string_piece.data(),
                                                   string_piece.size()) == -1) {
    download_data->output_file.Close();
    return false;
  }

  // Even when writing response to a file save the first 1 MiB of the response
  // body so that it can be used to get error information in case of server side
  // errors. The size limit is to avoid consuming too much redundant memory.
  const size_t kMaxStringSize = 1024 * 1024;
  if (download_data->response_body.size() < kMaxStringSize) {
    size_t bytes_to_copy =
        std::min(string_piece.size(),
                 kMaxStringSize - download_data->response_body.size());
    download_data->response_body.append(string_piece.data(), bytes_to_copy);
  }

  return true;
}

void UrlFetchRequestBase::OnWriteComplete(
    std::unique_ptr<DownloadData> download_data,
    base::OnceClosure resume,
    bool write_success) {
  download_data_ = std::move(download_data);
  if (!write_success) {
    error_code_ = DRIVE_OTHER_ERROR;
    url_loader_.reset();  // Cancel the request
    // No SimpleURLLoader to call OnComplete() so call it directly.
    OnComplete(false);
    return;
  }

  std::move(resume).Run();
}

void UrlFetchRequestBase::OnDataReceived(base::StringPiece string_piece,
                                         base::OnceClosure resume) {
  if (!download_data_->get_content_callback.is_null()) {
    download_data_->get_content_callback.Run(
        HTTP_SUCCESS, std::make_unique<std::string>(string_piece));
  }

  if (!download_data_->output_file_path.empty()) {
    DownloadData* download_data_ptr = download_data_.get();
    base::PostTaskAndReplyWithResult(
        blocking_task_runner(), FROM_HERE,
        base::BindOnce(&UrlFetchRequestBase::WriteFileData,
                       std::move(string_piece), download_data_ptr),
        base::BindOnce(&UrlFetchRequestBase::OnWriteComplete,
                       weak_ptr_factory_.GetWeakPtr(),
                       std::move(download_data_), std::move(resume)));
    return;
  }

  download_data_->response_body.append(string_piece.data(),
                                       string_piece.size());
  std::move(resume).Run();
}

void UrlFetchRequestBase::OnComplete(bool success) {
  DCHECK(download_data_);
  blocking_task_runner()->PostTaskAndReply(
      FROM_HERE,
      base::BindOnce(&CloseFile, std::move(download_data_->output_file)),
      base::BindOnce(&UrlFetchRequestBase::OnOutputFileClosed,
                     weak_ptr_factory_.GetWeakPtr(), success));
}

void UrlFetchRequestBase::OnOutputFileClosed(bool success) {
  DCHECK(download_data_);
  const network::ResourceResponseHead* response_info;
  if (url_loader_) {
    response_info = url_loader_->ResponseInfo();
    if (response_info) {
      error_code_ = static_cast<DriveApiErrorCode>(
          response_info->headers->response_code());
    } else {
      error_code_ = NetError() == net::ERR_NETWORK_CHANGED ? DRIVE_NO_CONNECTION
                                                           : DRIVE_OTHER_ERROR;
    }
    if (!download_data_->response_body.empty()) {
      error_code_ =
          MapJsonError(error_code_.value(), download_data_->response_body);
    }
  } else {
    // If the request is cancelled then error_code_ must be set.
    DCHECK(error_code_.has_value());
    response_info = nullptr;
  }

  if (error_code_.value() == HTTP_UNAUTHORIZED) {
    if (++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerRequest) {
      // Reset re_authenticate_callback_ so Start() can be called again.
      std::move(re_authenticate_callback_).Run(this);
      return;
    }
    OnAuthFailed(GetErrorCode());
    return;
  }

  // Overridden by each specialization
  ProcessURLFetchResults(response_info,
                         std::move(download_data_->output_file_path),
                         std::move(download_data_->response_body));
}

void UrlFetchRequestBase::OnRetry(base::OnceClosure start_retry) {
  NOTREACHED();
}

std::string UrlFetchRequestBase::GetRequestType() const {
  return "GET";
}

std::vector<std::string> UrlFetchRequestBase::GetExtraRequestHeaders() const {
  return std::vector<std::string>();
}

bool UrlFetchRequestBase::GetContentData(std::string* upload_content_type,
                                         std::string* upload_content) {
  return false;
}

bool UrlFetchRequestBase::GetContentFile(base::FilePath* local_file_path,
                                         int64_t* range_offset,
                                         int64_t* range_length,
                                         std::string* upload_content_type) {
  return false;
}

void UrlFetchRequestBase::GetOutputFilePath(
    base::FilePath* local_file_path,
    GetContentCallback* get_content_callback) {
}

void UrlFetchRequestBase::Cancel() {
  url_loader_.reset();
  CompleteRequestWithError(DRIVE_CANCELLED);
}

DriveApiErrorCode UrlFetchRequestBase::GetErrorCode() const {
  DCHECK(error_code_.has_value()) << "GetErrorCode only valid after "
                                     "resource load complete.";
  return error_code_.value();
}

int UrlFetchRequestBase::NetError() const {
  if (!url_loader_)  // If resource load cancelled?
    return net::ERR_FAILED;
  return url_loader_->NetError();
}

bool UrlFetchRequestBase::CalledOnValidThread() {
  return thread_checker_.CalledOnValidThread();
}

base::SequencedTaskRunner* UrlFetchRequestBase::blocking_task_runner() const {
  return sender_->blocking_task_runner();
}

void UrlFetchRequestBase::OnProcessURLFetchResultsComplete() {
  sender_->RequestFinished(this);
}

void UrlFetchRequestBase::CompleteRequestWithError(DriveApiErrorCode code) {
  RunCallbackOnPrematureFailure(code);
  sender_->RequestFinished(this);
}

void UrlFetchRequestBase::OnAuthFailed(DriveApiErrorCode code) {
  CompleteRequestWithError(code);
}

base::WeakPtr<AuthenticatedRequestInterface>
UrlFetchRequestBase::GetWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

//============================ EntryActionRequest ============================

EntryActionRequest::EntryActionRequest(RequestSender* sender,
                                       const EntryActionCallback& callback)
    : UrlFetchRequestBase(sender, ProgressCallback(), ProgressCallback()),
      callback_(callback) {
  DCHECK(!callback_.is_null());
}

EntryActionRequest::~EntryActionRequest() {}

void EntryActionRequest::ProcessURLFetchResults(
    const network::ResourceResponseHead* response_head,
    base::FilePath response_file,
    std::string response_body) {
  callback_.Run(GetErrorCode());
  OnProcessURLFetchResultsComplete();
}

void EntryActionRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) {
  callback_.Run(code);
}

//========================= InitiateUploadRequestBase ========================

InitiateUploadRequestBase::InitiateUploadRequestBase(
    RequestSender* sender,
    const InitiateUploadCallback& callback,
    const std::string& content_type,
    int64_t content_length)
    : UrlFetchRequestBase(sender, ProgressCallback(), ProgressCallback()),
      callback_(callback),
      content_type_(content_type),
      content_length_(content_length) {
  DCHECK(!callback_.is_null());
  DCHECK(!content_type_.empty());
  DCHECK_GE(content_length_, 0);
}

InitiateUploadRequestBase::~InitiateUploadRequestBase() {}

void InitiateUploadRequestBase::ProcessURLFetchResults(
    const network::ResourceResponseHead* response_head,
    base::FilePath response_file,
    std::string response_body) {
  std::string upload_location;
  if (GetErrorCode() == HTTP_SUCCESS) {
    // Retrieve value of the first "Location" header.
    response_head->headers->EnumerateHeader(nullptr, kUploadResponseLocation,
                                            &upload_location);
  }

  callback_.Run(GetErrorCode(), GURL(upload_location));
  OnProcessURLFetchResultsComplete();
}

void InitiateUploadRequestBase::RunCallbackOnPrematureFailure(
    DriveApiErrorCode code) {
  callback_.Run(code, GURL());
}

std::vector<std::string>
InitiateUploadRequestBase::GetExtraRequestHeaders() const {
  std::vector<std::string> headers;
  headers.push_back(kUploadContentType + content_type_);
  headers.push_back(
      kUploadContentLength + base::Int64ToString(content_length_));
  return headers;
}

//============================ UploadRangeResponse =============================

UploadRangeResponse::UploadRangeResponse()
    : code(HTTP_SUCCESS),
      start_position_received(0),
      end_position_received(0) {
}

UploadRangeResponse::UploadRangeResponse(DriveApiErrorCode code,
                                         int64_t start_position_received,
                                         int64_t end_position_received)
    : code(code),
      start_position_received(start_position_received),
      end_position_received(end_position_received) {}

UploadRangeResponse::~UploadRangeResponse() {
}

//========================== UploadRangeRequestBase ==========================

UploadRangeRequestBase::UploadRangeRequestBase(
    RequestSender* sender,
    const GURL& upload_url,
    const ProgressCallback& progress_callback)
    : UrlFetchRequestBase(sender, progress_callback, ProgressCallback()),
      upload_url_(upload_url),
      weak_ptr_factory_(this) {}

UploadRangeRequestBase::~UploadRangeRequestBase() {}

GURL UploadRangeRequestBase::GetURL() const {
  // This is very tricky to get json from this request. To do that, &alt=json
  // has to be appended not here but in InitiateUploadRequestBase::GetURL().
  return upload_url_;
}

std::string UploadRangeRequestBase::GetRequestType() const {
  return "PUT";
}

void UploadRangeRequestBase::ProcessURLFetchResults(
    const network::ResourceResponseHead* response_head,
    base::FilePath response_file,
    std::string response_body) {
  DriveApiErrorCode code = GetErrorCode();
  if (code == HTTP_RESUME_INCOMPLETE) {
    // Retrieve value of the first "Range" header.
    // The Range header is appeared only if there is at least one received
    // byte. So, initialize the positions by 0 so that the [0,0) will be
    // returned via the |callback_| for empty data case.
    int64_t start_position_received = 0;
    int64_t end_position_received = 0;
    std::string range_received;
    response_head->headers->EnumerateHeader(nullptr, kUploadResponseRange,
                                            &range_received);
    if (!range_received.empty()) {  // Parse the range header.
      std::vector<net::HttpByteRange> ranges;
      if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) &&
          !ranges.empty() ) {
        // We only care about the first start-end pair in the range.
        //
        // Range header represents the range inclusively, while we are treating
        // ranges exclusively (i.e., end_position_received should be one passed
        // the last valid index). So "+ 1" is added.
        start_position_received = ranges[0].first_byte_position();
        end_position_received = ranges[0].last_byte_position() + 1;
      }
    }
    // The Range header has the received data range, so the start position
    // should be always 0.
    DCHECK_EQ(start_position_received, 0);

    OnRangeRequestComplete(UploadRangeResponse(code, start_position_received,
                                               end_position_received),
                           std::unique_ptr<base::Value>());

    OnProcessURLFetchResultsComplete();
  } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
    // The upload is successfully done. Parse the response which should be
    // the entry's metadata.
    ParseJsonOnBlockingPool(
        blocking_task_runner(), std::move(response_body),
        base::BindOnce(&UploadRangeRequestBase::OnDataParsed,
                       weak_ptr_factory_.GetWeakPtr(), code));
  } else {
    // Failed to upload. Run callbacks to notify the error.
    OnRangeRequestComplete(UploadRangeResponse(code, -1, -1),
                           std::unique_ptr<base::Value>());
    OnProcessURLFetchResultsComplete();
  }
}

void UploadRangeRequestBase::OnDataParsed(DriveApiErrorCode code,
                                          std::unique_ptr<base::Value> value) {
  DCHECK(CalledOnValidThread());
  DCHECK(code == HTTP_CREATED || code == HTTP_SUCCESS);

  OnRangeRequestComplete(UploadRangeResponse(code, -1, -1), std::move(value));
  OnProcessURLFetchResultsComplete();
}

void UploadRangeRequestBase::RunCallbackOnPrematureFailure(
    DriveApiErrorCode code) {
  OnRangeRequestComplete(UploadRangeResponse(code, 0, 0),
                         std::unique_ptr<base::Value>());
}

UploadRangeRequestBase::DownloadData::DownloadData(
    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
    : blocking_task_runner_(blocking_task_runner) {}

UploadRangeRequestBase::DownloadData::~DownloadData() {
  if (output_file.IsValid()) {
    blocking_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&CloseFile, std::move(output_file)));
  }
}

//========================== ResumeUploadRequestBase =========================

ResumeUploadRequestBase::ResumeUploadRequestBase(
    RequestSender* sender,
    const GURL& upload_location,
    int64_t start_position,
    int64_t end_position,
    int64_t content_length,
    const std::string& content_type,
    const base::FilePath& local_file_path,
    const ProgressCallback& progress_callback)
    : UploadRangeRequestBase(sender, upload_location, progress_callback),
      start_position_(start_position),
      end_position_(end_position),
      content_length_(content_length),
      content_type_(content_type),
      local_file_path_(local_file_path) {
  DCHECK_LE(start_position_, end_position_);
}

ResumeUploadRequestBase::~ResumeUploadRequestBase() {}

std::vector<std::string>
ResumeUploadRequestBase::GetExtraRequestHeaders() const {
  if (content_length_ == 0) {
    // For uploading an empty document, just PUT an empty content.
    DCHECK_EQ(start_position_, 0);
    DCHECK_EQ(end_position_, 0);
    return std::vector<std::string>();
  }

  // The header looks like
  // Content-Range: bytes <start_position>-<end_position>/<content_length>
  // for example:
  // Content-Range: bytes 7864320-8388607/13851821
  // The header takes inclusive range, so we adjust by "end_position - 1".
  DCHECK_GE(start_position_, 0);
  DCHECK_GT(end_position_, 0);
  DCHECK_GE(content_length_, 0);

  std::vector<std::string> headers;
  headers.push_back(
      std::string(kUploadContentRange) +
      base::Int64ToString(start_position_) + "-" +
      base::Int64ToString(end_position_ - 1) + "/" +
      base::Int64ToString(content_length_));
  return headers;
}

bool ResumeUploadRequestBase::GetContentFile(base::FilePath* local_file_path,
                                             int64_t* range_offset,
                                             int64_t* range_length,
                                             std::string* upload_content_type) {
  if (start_position_ == end_position_) {
    // No content data.
    return false;
  }

  *local_file_path = local_file_path_;
  *range_offset = start_position_;
  *range_length = end_position_ - start_position_;
  *upload_content_type = content_type_;
  return true;
}

//======================== GetUploadStatusRequestBase ========================

GetUploadStatusRequestBase::GetUploadStatusRequestBase(RequestSender* sender,
                                                       const GURL& upload_url,
                                                       int64_t content_length)
    : UploadRangeRequestBase(sender, upload_url, ProgressCallback()),
      content_length_(content_length) {}

GetUploadStatusRequestBase::~GetUploadStatusRequestBase() {}

std::vector<std::string>
GetUploadStatusRequestBase::GetExtraRequestHeaders() const {
  // The header looks like
  // Content-Range: bytes */<content_length>
  // for example:
  // Content-Range: bytes */13851821
  DCHECK_GE(content_length_, 0);

  std::vector<std::string> headers;
  headers.push_back(
      std::string(kUploadContentRange) + "*/" +
      base::Int64ToString(content_length_));
  return headers;
}

//========================= MultipartUploadRequestBase ========================

MultipartUploadRequestBase::MultipartUploadRequestBase(
    base::SequencedTaskRunner* blocking_task_runner,
    const std::string& metadata_json,
    const std::string& content_type,
    int64_t content_length,
    const base::FilePath& local_file_path,
    const FileResourceCallback& callback,
    const ProgressCallback& progress_callback)
    : blocking_task_runner_(blocking_task_runner),
      metadata_json_(metadata_json),
      content_type_(content_type),
      local_path_(local_file_path),
      callback_(callback),
      progress_callback_(progress_callback),
      weak_ptr_factory_(this) {
  DCHECK(!content_type.empty());
  DCHECK_GE(content_length, 0);
  DCHECK(!local_file_path.empty());
  DCHECK(!callback.is_null());
}

MultipartUploadRequestBase::~MultipartUploadRequestBase() {
}

std::vector<std::string> MultipartUploadRequestBase::GetExtraRequestHeaders()
    const {
  return std::vector<std::string>();
}

void MultipartUploadRequestBase::Prepare(const PrepareCallback& callback) {
  // If the request is cancelled, the request instance will be deleted in
  // |UrlFetchRequestBase::Cancel| and OnPrepareUploadContent won't be called.
  std::string* const upload_content_type = new std::string();
  std::string* const upload_content_data = new std::string();
  PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&GetMultipartContent, boundary_, metadata_json_, content_type_,
                 local_path_, base::Unretained(upload_content_type),
                 base::Unretained(upload_content_data)),
      base::Bind(&MultipartUploadRequestBase::OnPrepareUploadContent,
                 weak_ptr_factory_.GetWeakPtr(), callback,
                 base::Owned(upload_content_type),
                 base::Owned(upload_content_data)));
}

void MultipartUploadRequestBase::OnPrepareUploadContent(
    const PrepareCallback& callback,
    std::string* upload_content_type,
    std::string* upload_content_data,
    bool result) {
  if (!result) {
    callback.Run(DRIVE_FILE_ERROR);
    return;
  }
  upload_content_type_.swap(*upload_content_type);
  upload_content_data_.swap(*upload_content_data);
  callback.Run(HTTP_SUCCESS);
}

void MultipartUploadRequestBase::SetBoundaryForTesting(
    const std::string& boundary) {
  boundary_ = boundary;
}

bool MultipartUploadRequestBase::GetContentData(
    std::string* upload_content_type,
    std::string* upload_content_data) {
  // TODO(hirono): Pass stream instead of actual data to reduce memory usage.
  upload_content_type->swap(upload_content_type_);
  upload_content_data->swap(upload_content_data_);
  return true;
}

void MultipartUploadRequestBase::NotifyResult(
    DriveApiErrorCode code,
    const std::string& body,
    const base::Closure& notify_complete_callback) {
  // The upload is successfully done. Parse the response which should be
  // the entry's metadata.
  if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
    ParseJsonOnBlockingPool(
        blocking_task_runner_.get(), body,
        base::BindOnce(&MultipartUploadRequestBase::OnDataParsed,
                       weak_ptr_factory_.GetWeakPtr(), code,
                       notify_complete_callback));
  } else {
    NotifyError(MapJsonError(code, body));
    notify_complete_callback.Run();
  }
}

void MultipartUploadRequestBase::NotifyError(DriveApiErrorCode code) {
  callback_.Run(code, std::unique_ptr<FileResource>());
}

void MultipartUploadRequestBase::NotifyUploadProgress(int64_t current,
                                                      int64_t total) {
  if (!progress_callback_.is_null())
    progress_callback_.Run(current, total);
}

void MultipartUploadRequestBase::OnDataParsed(
    DriveApiErrorCode code,
    const base::Closure& notify_complete_callback,
    std::unique_ptr<base::Value> value) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (value)
    callback_.Run(code, google_apis::FileResource::CreateFrom(*value));
  else
    NotifyError(DRIVE_PARSE_ERROR);
  notify_complete_callback.Run();
}

//============================ DownloadFileRequestBase =========================

DownloadFileRequestBase::DownloadFileRequestBase(
    RequestSender* sender,
    const DownloadActionCallback& download_action_callback,
    const GetContentCallback& get_content_callback,
    const ProgressCallback& progress_callback,
    const GURL& download_url,
    const base::FilePath& output_file_path)
    : UrlFetchRequestBase(sender, ProgressCallback(), progress_callback),
      download_action_callback_(download_action_callback),
      get_content_callback_(get_content_callback),
      download_url_(download_url),
      output_file_path_(output_file_path) {
  DCHECK(!download_action_callback_.is_null());
  DCHECK(!output_file_path_.empty());
  // get_content_callback may be null.
}

DownloadFileRequestBase::~DownloadFileRequestBase() {}

// Overridden from UrlFetchRequestBase.
GURL DownloadFileRequestBase::GetURL() const {
  return download_url_;
}

void DownloadFileRequestBase::GetOutputFilePath(
    base::FilePath* local_file_path,
    GetContentCallback* get_content_callback) {
  // Configure so that the downloaded content is saved to |output_file_path_|.
  *local_file_path = output_file_path_;
  *get_content_callback = get_content_callback_;
}

void DownloadFileRequestBase::ProcessURLFetchResults(
    const network::ResourceResponseHead* response_head,
    base::FilePath response_file,
    std::string response_body) {
  download_action_callback_.Run(GetErrorCode(), response_file);
  OnProcessURLFetchResultsComplete();
}

void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
    DriveApiErrorCode code) {
  download_action_callback_.Run(code, base::FilePath());
}

}  // namespace google_apis
