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

#include <stddef.h>

#include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/values.h"
#include "google_apis/drive/request_sender.h"
#include "google_apis/drive/request_util.h"
#include "google_apis/drive/time_util.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"

namespace google_apis {
namespace drive {
namespace {

// Format of one request in batch uploading request.
const char kBatchUploadRequestFormat[] =
    "%s %s HTTP/1.1\n"
    "Host: %s\n"
    "X-Goog-Upload-Protocol: multipart\n"
    "Content-Type: %s\n"
    "\n";

// Request header for specifying batch upload.
const char kBatchUploadHeader[] = "X-Goog-Upload-Protocol: batch";

// Content type of HTTP request.
const char kHttpContentType[] = "application/http";

// Break line in HTTP message.
const char kHttpBr[] = "\r\n";

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

// UMA names.
const char kUMADriveBatchUploadResponseCode[] = "Drive.BatchUploadResponseCode";
const char kUMADriveTotalFileCountInBatchUpload[] =
    "Drive.TotalFileCountInBatchUpload";
const char kUMADriveTotalFileSizeInBatchUpload[] =
    "Drive.TotalFileSizeInBatchUpload";

// Parses the JSON value to FileResource instance and runs |callback| on the
// UI thread once parsing is done.
// This is customized version of ParseJsonAndRun defined above to adapt the
// remaining response type.
void ParseFileResourceWithUploadRangeAndRun(
    const UploadRangeCallback& callback,
    const UploadRangeResponse& response,
    std::unique_ptr<base::Value> value) {
  DCHECK(!callback.is_null());

  std::unique_ptr<FileResource> file_resource;
  if (value) {
    file_resource = FileResource::CreateFrom(*value);
    if (!file_resource) {
      callback.Run(UploadRangeResponse(DRIVE_PARSE_ERROR,
                                       response.start_position_received,
                                       response.end_position_received),
                   std::unique_ptr<FileResource>());
      return;
    }
  }

  callback.Run(response, std::move(file_resource));
}

// Attaches |properties| to the |request_body| if |properties| is not empty.
// |request_body| must not be NULL.
void AttachProperties(const Properties& properties,
                      base::DictionaryValue* request_body) {
  DCHECK(request_body);
  if (properties.empty())
    return;

  base::ListValue* const properties_value = new base::ListValue;
  for (const auto& property : properties) {
    base::DictionaryValue* const property_value = new base::DictionaryValue;
    std::string visibility_as_string;
    switch (property.visibility()) {
      case Property::VISIBILITY_PRIVATE:
        visibility_as_string = "PRIVATE";
        break;
      case Property::VISIBILITY_PUBLIC:
        visibility_as_string = "PUBLIC";
        break;
    }
    property_value->SetString("visibility", visibility_as_string);
    property_value->SetString("key", property.key());
    property_value->SetString("value", property.value());
    properties_value->Append(property_value);
  }
  request_body->Set("properties", properties_value);
}

// Creates metadata JSON string for multipart uploading.
// All the values are optional. If the value is empty or null, the value does
// not appear in the metadata.
std::string CreateMultipartUploadMetadataJson(
    const std::string& title,
    const std::string& parent_resource_id,
    const base::Time& modified_date,
    const base::Time& last_viewed_by_me_date,
    const Properties& properties) {
  base::DictionaryValue root;
  if (!title.empty())
    root.SetString("title", title);

  // Fill parent link.
  if (!parent_resource_id.empty()) {
    std::unique_ptr<base::ListValue> parents(new base::ListValue);
    parents->Append(google_apis::util::CreateParentValue(parent_resource_id));
    root.Set("parents", parents.release());
  }

  if (!modified_date.is_null()) {
    root.SetString("modifiedDate",
                   google_apis::util::FormatTimeAsString(modified_date));
  }

  if (!last_viewed_by_me_date.is_null()) {
    root.SetString("lastViewedByMeDate", google_apis::util::FormatTimeAsString(
                                             last_viewed_by_me_date));
  }

  AttachProperties(properties, &root);
  std::string json_string;
  base::JSONWriter::Write(root, &json_string);
  return json_string;
}

}  // namespace

MultipartHttpResponse::MultipartHttpResponse() : code(HTTP_SUCCESS) {
}

MultipartHttpResponse::~MultipartHttpResponse() {
}

// The |response| must be multipart/mixed format that contains child HTTP
// response of drive batch request.
// https://www.ietf.org/rfc/rfc2046.txt
//
// It looks like:
// --Boundary
// Content-type: application/http
//
// HTTP/1.1 200 OK
// Header of child response
//
// Body of child response
// --Boundary
// Content-type: application/http
//
// HTTP/1.1 404 Not Found
// Header of child response
//
// Body of child response
// --Boundary--
bool ParseMultipartResponse(const std::string& content_type,
                            const std::string& response,
                            std::vector<MultipartHttpResponse>* parts) {
  if (response.empty())
    return false;

  base::StringPiece content_type_piece(content_type);
  if (!content_type_piece.starts_with(kMultipartMixedMimeTypePrefix)) {
    return false;
  }
  content_type_piece.remove_prefix(
      base::StringPiece(kMultipartMixedMimeTypePrefix).size());

  if (content_type_piece.empty())
    return false;
  if (content_type_piece[0] == '"') {
    if (content_type_piece.size() <= 2 || content_type_piece.back() != '"')
      return false;

    content_type_piece =
        content_type_piece.substr(1, content_type_piece.size() - 2);
  }

  std::string boundary;
  content_type_piece.CopyToString(&boundary);
  const std::string header = "--" + boundary;
  const std::string terminator = "--" + boundary + "--";

  std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr(
      response, kHttpBr, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);

  enum {
    STATE_START,
    STATE_PART_HEADER,
    STATE_PART_HTTP_STATUS_LINE,
    STATE_PART_HTTP_HEADER,
    STATE_PART_HTTP_BODY
  } state = STATE_START;

  const std::string kHttpStatusPrefix = "HTTP/1.1 ";
  std::vector<MultipartHttpResponse> responses;
  DriveApiErrorCode code = DRIVE_PARSE_ERROR;
  std::string body;
  for (const auto& line : lines) {
    if (state == STATE_PART_HEADER && line.empty()) {
      state = STATE_PART_HTTP_STATUS_LINE;
      continue;
    }

    if (state == STATE_PART_HTTP_STATUS_LINE) {
      if (line.starts_with(kHttpStatusPrefix)) {
        int int_code;
        base::StringToInt(
            line.substr(base::StringPiece(kHttpStatusPrefix).size()),
            &int_code);
        if (int_code > 0)
          code = static_cast<DriveApiErrorCode>(int_code);
        else
          code = DRIVE_PARSE_ERROR;
      } else {
        code = DRIVE_PARSE_ERROR;
      }
      state = STATE_PART_HTTP_HEADER;
      continue;
    }

    if (state == STATE_PART_HTTP_HEADER && line.empty()) {
      state = STATE_PART_HTTP_BODY;
      body.clear();
      continue;
    }
    const base::StringPiece chopped_line =
        base::TrimString(line, " \t", base::TRIM_TRAILING);
    const bool is_new_part = chopped_line == header;
    const bool was_last_part = chopped_line == terminator;
    if (is_new_part || was_last_part) {
      switch (state) {
        case STATE_START:
          break;
        case STATE_PART_HEADER:
        case STATE_PART_HTTP_STATUS_LINE:
          responses.push_back(MultipartHttpResponse());
          responses.back().code = DRIVE_PARSE_ERROR;
          break;
        case STATE_PART_HTTP_HEADER:
          responses.push_back(MultipartHttpResponse());
          responses.back().code = code;
          break;
        case STATE_PART_HTTP_BODY:
          // Drop the last kHttpBr.
          if (!body.empty())
            body.resize(body.size() - 2);
          responses.push_back(MultipartHttpResponse());
          responses.back().code = code;
          responses.back().body.swap(body);
          break;
      }
      if (is_new_part)
        state = STATE_PART_HEADER;
      if (was_last_part)
        break;
    } else if (state == STATE_PART_HTTP_BODY) {
      line.AppendToString(&body);
      body.append(kHttpBr);
    }
  }

  parts->swap(responses);
  return true;
}

Property::Property() : visibility_(VISIBILITY_PRIVATE) {
}

Property::~Property() {
}

//============================ DriveApiPartialFieldRequest ====================

DriveApiPartialFieldRequest::DriveApiPartialFieldRequest(
    RequestSender* sender) : UrlFetchRequestBase(sender) {
}

DriveApiPartialFieldRequest::~DriveApiPartialFieldRequest() {
}

GURL DriveApiPartialFieldRequest::GetURL() const {
  GURL url = GetURLInternal();
  if (!fields_.empty())
    url = net::AppendOrReplaceQueryParameter(url, "fields", fields_);
  return url;
}

//=============================== FilesGetRequest =============================

FilesGetRequest::FilesGetRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    bool use_internal_endpoint,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator),
      use_internal_endpoint_(use_internal_endpoint) {
  DCHECK(!callback.is_null());
}

FilesGetRequest::~FilesGetRequest() {}

GURL FilesGetRequest::GetURLInternal() const {
  return url_generator_.GetFilesGetUrl(file_id_,
                                       use_internal_endpoint_,
                                       embed_origin_);
}

//============================ FilesAuthorizeRequest ===========================

FilesAuthorizeRequest::FilesAuthorizeRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

FilesAuthorizeRequest::~FilesAuthorizeRequest() {}

net::URLFetcher::RequestType FilesAuthorizeRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

GURL FilesAuthorizeRequest::GetURLInternal() const {
  return url_generator_.GetFilesAuthorizeUrl(file_id_, app_id_);
}

//============================ FilesInsertRequest ============================

FilesInsertRequest::FilesInsertRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator),
      visibility_(FILE_VISIBILITY_DEFAULT) {
  DCHECK(!callback.is_null());
}

FilesInsertRequest::~FilesInsertRequest() {}

net::URLFetcher::RequestType FilesInsertRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

bool FilesInsertRequest::GetContentData(std::string* upload_content_type,
                                        std::string* upload_content) {
  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;

  if (!last_viewed_by_me_date_.is_null()) {
    root.SetString("lastViewedByMeDate",
                   util::FormatTimeAsString(last_viewed_by_me_date_));
  }

  if (!mime_type_.empty())
    root.SetString("mimeType", mime_type_);

  if (!modified_date_.is_null())
    root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));

  if (!parents_.empty()) {
    base::ListValue* parents_value = new base::ListValue;
    for (size_t i = 0; i < parents_.size(); ++i) {
      std::unique_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
      parent->SetString("id", parents_[i]);
      parents_value->Append(std::move(parent));
    }
    root.Set("parents", parents_value);
  }

  if (!title_.empty())
    root.SetString("title", title_);

  AttachProperties(properties_, &root);
  base::JSONWriter::Write(root, upload_content);

  DVLOG(1) << "FilesInsert data: " << *upload_content_type << ", ["
           << *upload_content << "]";
  return true;
}

GURL FilesInsertRequest::GetURLInternal() const {
  return url_generator_.GetFilesInsertUrl(
      visibility_ == FILE_VISIBILITY_PRIVATE ? "PRIVATE" : "");
}

//============================== FilesPatchRequest ============================

FilesPatchRequest::FilesPatchRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator),
      set_modified_date_(false),
      update_viewed_date_(true) {
  DCHECK(!callback.is_null());
}

FilesPatchRequest::~FilesPatchRequest() {}

net::URLFetcher::RequestType FilesPatchRequest::GetRequestType() const {
  return net::URLFetcher::PATCH;
}

std::vector<std::string> FilesPatchRequest::GetExtraRequestHeaders() const {
  std::vector<std::string> headers;
  headers.push_back(util::kIfMatchAllHeader);
  return headers;
}

GURL FilesPatchRequest::GetURLInternal() const {
  return url_generator_.GetFilesPatchUrl(
      file_id_, set_modified_date_, update_viewed_date_);
}

bool FilesPatchRequest::GetContentData(std::string* upload_content_type,
                                       std::string* upload_content) {
  if (title_.empty() &&
      modified_date_.is_null() &&
      last_viewed_by_me_date_.is_null() &&
      parents_.empty())
    return false;

  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;
  if (!title_.empty())
    root.SetString("title", title_);

  if (!modified_date_.is_null())
    root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));

  if (!last_viewed_by_me_date_.is_null()) {
    root.SetString("lastViewedByMeDate",
                   util::FormatTimeAsString(last_viewed_by_me_date_));
  }

  if (!parents_.empty()) {
    base::ListValue* parents_value = new base::ListValue;
    for (size_t i = 0; i < parents_.size(); ++i) {
      std::unique_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
      parent->SetString("id", parents_[i]);
      parents_value->Append(std::move(parent));
    }
    root.Set("parents", parents_value);
  }

  AttachProperties(properties_, &root);
  base::JSONWriter::Write(root, upload_content);

  DVLOG(1) << "FilesPatch data: " << *upload_content_type << ", ["
           << *upload_content << "]";
  return true;
}

//============================= FilesCopyRequest ==============================

FilesCopyRequest::FilesCopyRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator),
      visibility_(FILE_VISIBILITY_DEFAULT) {
  DCHECK(!callback.is_null());
}

FilesCopyRequest::~FilesCopyRequest() {
}

net::URLFetcher::RequestType FilesCopyRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

GURL FilesCopyRequest::GetURLInternal() const {
  return url_generator_.GetFilesCopyUrl(
      file_id_, visibility_ == FILE_VISIBILITY_PRIVATE ? "PRIVATE" : "");
}

bool FilesCopyRequest::GetContentData(std::string* upload_content_type,
                                      std::string* upload_content) {
  if (parents_.empty() && title_.empty())
    return false;

  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;

  if (!modified_date_.is_null())
    root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));

  if (!parents_.empty()) {
    base::ListValue* parents_value = new base::ListValue;
    for (size_t i = 0; i < parents_.size(); ++i) {
      std::unique_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
      parent->SetString("id", parents_[i]);
      parents_value->Append(std::move(parent));
    }
    root.Set("parents", parents_value);
  }

  if (!title_.empty())
    root.SetString("title", title_);

  base::JSONWriter::Write(root, upload_content);
  DVLOG(1) << "FilesCopy data: " << *upload_content_type << ", ["
           << *upload_content << "]";
  return true;
}

//============================= FilesListRequest =============================

FilesListRequest::FilesListRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileListCallback& callback)
    : DriveApiDataRequest<FileList>(sender, callback),
      url_generator_(url_generator),
      max_results_(100) {
  DCHECK(!callback.is_null());
}

FilesListRequest::~FilesListRequest() {}

GURL FilesListRequest::GetURLInternal() const {
  return url_generator_.GetFilesListUrl(max_results_, page_token_, q_);
}

//======================== FilesListNextPageRequest =========================

FilesListNextPageRequest::FilesListNextPageRequest(
    RequestSender* sender,
    const FileListCallback& callback)
    : DriveApiDataRequest<FileList>(sender, callback) {
  DCHECK(!callback.is_null());
}

FilesListNextPageRequest::~FilesListNextPageRequest() {
}

GURL FilesListNextPageRequest::GetURLInternal() const {
  return next_link_;
}

//============================ FilesDeleteRequest =============================

FilesDeleteRequest::FilesDeleteRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const EntryActionCallback& callback)
    : EntryActionRequest(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

FilesDeleteRequest::~FilesDeleteRequest() {}

net::URLFetcher::RequestType FilesDeleteRequest::GetRequestType() const {
  return net::URLFetcher::DELETE_REQUEST;
}

GURL FilesDeleteRequest::GetURL() const {
  return url_generator_.GetFilesDeleteUrl(file_id_);
}

std::vector<std::string> FilesDeleteRequest::GetExtraRequestHeaders() const {
  std::vector<std::string> headers(
      EntryActionRequest::GetExtraRequestHeaders());
  headers.push_back(util::GenerateIfMatchHeader(etag_));
  return headers;
}

//============================ FilesTrashRequest =============================

FilesTrashRequest::FilesTrashRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback)
    : DriveApiDataRequest<FileResource>(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

FilesTrashRequest::~FilesTrashRequest() {}

net::URLFetcher::RequestType FilesTrashRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

GURL FilesTrashRequest::GetURLInternal() const {
  return url_generator_.GetFilesTrashUrl(file_id_);
}

//============================== AboutGetRequest =============================

AboutGetRequest::AboutGetRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const AboutResourceCallback& callback)
    : DriveApiDataRequest<AboutResource>(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

AboutGetRequest::~AboutGetRequest() {}

GURL AboutGetRequest::GetURLInternal() const {
  return url_generator_.GetAboutGetUrl();
}

//============================ ChangesListRequest ===========================

ChangesListRequest::ChangesListRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const ChangeListCallback& callback)
    : DriveApiDataRequest<ChangeList>(sender, callback),
      url_generator_(url_generator),
      include_deleted_(true),
      max_results_(100),
      start_change_id_(0) {
  DCHECK(!callback.is_null());
}

ChangesListRequest::~ChangesListRequest() {}

GURL ChangesListRequest::GetURLInternal() const {
  return url_generator_.GetChangesListUrl(
      include_deleted_, max_results_, page_token_, start_change_id_);
}

//======================== ChangesListNextPageRequest =========================

ChangesListNextPageRequest::ChangesListNextPageRequest(
    RequestSender* sender,
    const ChangeListCallback& callback)
    : DriveApiDataRequest<ChangeList>(sender, callback) {
  DCHECK(!callback.is_null());
}

ChangesListNextPageRequest::~ChangesListNextPageRequest() {
}

GURL ChangesListNextPageRequest::GetURLInternal() const {
  return next_link_;
}

//============================== AppsListRequest ===========================

AppsListRequest::AppsListRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    bool use_internal_endpoint,
    const AppListCallback& callback)
    : DriveApiDataRequest<AppList>(sender, callback),
      url_generator_(url_generator),
      use_internal_endpoint_(use_internal_endpoint) {
  DCHECK(!callback.is_null());
}

AppsListRequest::~AppsListRequest() {}

GURL AppsListRequest::GetURLInternal() const {
  return url_generator_.GetAppsListUrl(use_internal_endpoint_);
}

//============================== AppsDeleteRequest ===========================

AppsDeleteRequest::AppsDeleteRequest(RequestSender* sender,
                                     const DriveApiUrlGenerator& url_generator,
                                     const EntryActionCallback& callback)
    : EntryActionRequest(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

AppsDeleteRequest::~AppsDeleteRequest() {}

net::URLFetcher::RequestType AppsDeleteRequest::GetRequestType() const {
  return net::URLFetcher::DELETE_REQUEST;
}

GURL AppsDeleteRequest::GetURL() const {
  return url_generator_.GetAppsDeleteUrl(app_id_);
}

//========================== ChildrenInsertRequest ============================

ChildrenInsertRequest::ChildrenInsertRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const EntryActionCallback& callback)
    : EntryActionRequest(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

ChildrenInsertRequest::~ChildrenInsertRequest() {}

net::URLFetcher::RequestType ChildrenInsertRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

GURL ChildrenInsertRequest::GetURL() const {
  return url_generator_.GetChildrenInsertUrl(folder_id_);
}

bool ChildrenInsertRequest::GetContentData(std::string* upload_content_type,
                                           std::string* upload_content) {
  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;
  root.SetString("id", id_);

  base::JSONWriter::Write(root, upload_content);
  DVLOG(1) << "InsertResource data: " << *upload_content_type << ", ["
           << *upload_content << "]";
  return true;
}

//========================== ChildrenDeleteRequest ============================

ChildrenDeleteRequest::ChildrenDeleteRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const EntryActionCallback& callback)
    : EntryActionRequest(sender, callback),
      url_generator_(url_generator) {
  DCHECK(!callback.is_null());
}

ChildrenDeleteRequest::~ChildrenDeleteRequest() {}

net::URLFetcher::RequestType ChildrenDeleteRequest::GetRequestType() const {
  return net::URLFetcher::DELETE_REQUEST;
}

GURL ChildrenDeleteRequest::GetURL() const {
  return url_generator_.GetChildrenDeleteUrl(child_id_, folder_id_);
}

//======================= InitiateUploadNewFileRequest =======================

InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const std::string& content_type,
    int64_t content_length,
    const std::string& parent_resource_id,
    const std::string& title,
    const InitiateUploadCallback& callback)
    : InitiateUploadRequestBase(sender, callback, content_type, content_length),
      url_generator_(url_generator),
      parent_resource_id_(parent_resource_id),
      title_(title) {}

InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {}

GURL InitiateUploadNewFileRequest::GetURL() const {
  return url_generator_.GetInitiateUploadNewFileUrl(!modified_date_.is_null());
}

net::URLFetcher::RequestType
InitiateUploadNewFileRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

bool InitiateUploadNewFileRequest::GetContentData(
    std::string* upload_content_type,
    std::string* upload_content) {
  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;
  root.SetString("title", title_);

  // Fill parent link.
  std::unique_ptr<base::ListValue> parents(new base::ListValue);
  parents->Append(util::CreateParentValue(parent_resource_id_));
  root.Set("parents", parents.release());

  if (!modified_date_.is_null())
    root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));

  if (!last_viewed_by_me_date_.is_null()) {
    root.SetString("lastViewedByMeDate",
                   util::FormatTimeAsString(last_viewed_by_me_date_));
  }

  AttachProperties(properties_, &root);
  base::JSONWriter::Write(root, upload_content);

  DVLOG(1) << "InitiateUploadNewFile data: " << *upload_content_type << ", ["
           << *upload_content << "]";
  return true;
}

//===================== InitiateUploadExistingFileRequest ====================

InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const std::string& content_type,
    int64_t content_length,
    const std::string& resource_id,
    const std::string& etag,
    const InitiateUploadCallback& callback)
    : InitiateUploadRequestBase(sender, callback, content_type, content_length),
      url_generator_(url_generator),
      resource_id_(resource_id),
      etag_(etag) {}

InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {}

GURL InitiateUploadExistingFileRequest::GetURL() const {
  return url_generator_.GetInitiateUploadExistingFileUrl(
      resource_id_, !modified_date_.is_null());
}

net::URLFetcher::RequestType
InitiateUploadExistingFileRequest::GetRequestType() const {
  return net::URLFetcher::PUT;
}

std::vector<std::string>
InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const {
  std::vector<std::string> headers(
      InitiateUploadRequestBase::GetExtraRequestHeaders());
  headers.push_back(util::GenerateIfMatchHeader(etag_));
  return headers;
}

bool InitiateUploadExistingFileRequest::GetContentData(
    std::string* upload_content_type,
    std::string* upload_content) {
  base::DictionaryValue root;
  if (!parent_resource_id_.empty()) {
    std::unique_ptr<base::ListValue> parents(new base::ListValue);
    parents->Append(util::CreateParentValue(parent_resource_id_));
    root.Set("parents", parents.release());
  }

  if (!title_.empty())
    root.SetString("title", title_);

  if (!modified_date_.is_null())
    root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));

  if (!last_viewed_by_me_date_.is_null()) {
    root.SetString("lastViewedByMeDate",
                   util::FormatTimeAsString(last_viewed_by_me_date_));
  }

  AttachProperties(properties_, &root);
  if (root.empty())
    return false;

  *upload_content_type = util::kContentTypeApplicationJson;
  base::JSONWriter::Write(root, upload_content);
  DVLOG(1) << "InitiateUploadExistingFile data: " << *upload_content_type
           << ", [" << *upload_content << "]";
  return true;
}

//============================ ResumeUploadRequest ===========================

ResumeUploadRequest::ResumeUploadRequest(
    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 UploadRangeCallback& callback,
    const ProgressCallback& progress_callback)
    : ResumeUploadRequestBase(sender,
                              upload_location,
                              start_position,
                              end_position,
                              content_length,
                              content_type,
                              local_file_path),
      callback_(callback),
      progress_callback_(progress_callback) {
  DCHECK(!callback_.is_null());
}

ResumeUploadRequest::~ResumeUploadRequest() {}

void ResumeUploadRequest::OnRangeRequestComplete(
    const UploadRangeResponse& response,
    std::unique_ptr<base::Value> value) {
  DCHECK(CalledOnValidThread());
  ParseFileResourceWithUploadRangeAndRun(callback_, response, std::move(value));
}

void ResumeUploadRequest::OnURLFetchUploadProgress(
    const net::URLFetcher* source,
    int64_t current,
    int64_t total) {
  if (!progress_callback_.is_null())
    progress_callback_.Run(current, total);
}

//========================== GetUploadStatusRequest ==========================

GetUploadStatusRequest::GetUploadStatusRequest(
    RequestSender* sender,
    const GURL& upload_url,
    int64_t content_length,
    const UploadRangeCallback& callback)
    : GetUploadStatusRequestBase(sender, upload_url, content_length),
      callback_(callback) {
  DCHECK(!callback.is_null());
}

GetUploadStatusRequest::~GetUploadStatusRequest() {}

void GetUploadStatusRequest::OnRangeRequestComplete(
    const UploadRangeResponse& response,
    std::unique_ptr<base::Value> value) {
  DCHECK(CalledOnValidThread());
  ParseFileResourceWithUploadRangeAndRun(callback_, response, std::move(value));
}

//======================= MultipartUploadNewFileDelegate =======================

MultipartUploadNewFileDelegate::MultipartUploadNewFileDelegate(
    base::SequencedTaskRunner* task_runner,
    const std::string& title,
    const std::string& parent_resource_id,
    const std::string& content_type,
    int64_t content_length,
    const base::Time& modified_date,
    const base::Time& last_viewed_by_me_date,
    const base::FilePath& local_file_path,
    const Properties& properties,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback,
    const ProgressCallback& progress_callback)
    : MultipartUploadRequestBase(
          task_runner,
          CreateMultipartUploadMetadataJson(title,
                                            parent_resource_id,
                                            modified_date,
                                            last_viewed_by_me_date,
                                            properties),
          content_type,
          content_length,
          local_file_path,
          callback,
          progress_callback),
      has_modified_date_(!modified_date.is_null()),
      url_generator_(url_generator) {}

MultipartUploadNewFileDelegate::~MultipartUploadNewFileDelegate() {
}

GURL MultipartUploadNewFileDelegate::GetURL() const {
  return url_generator_.GetMultipartUploadNewFileUrl(has_modified_date_);
}

net::URLFetcher::RequestType MultipartUploadNewFileDelegate::GetRequestType()
    const {
  return net::URLFetcher::POST;
}

//====================== MultipartUploadExistingFileDelegate ===================

MultipartUploadExistingFileDelegate::MultipartUploadExistingFileDelegate(
    base::SequencedTaskRunner* task_runner,
    const std::string& title,
    const std::string& resource_id,
    const std::string& parent_resource_id,
    const std::string& content_type,
    int64_t content_length,
    const base::Time& modified_date,
    const base::Time& last_viewed_by_me_date,
    const base::FilePath& local_file_path,
    const std::string& etag,
    const Properties& properties,
    const DriveApiUrlGenerator& url_generator,
    const FileResourceCallback& callback,
    const ProgressCallback& progress_callback)
    : MultipartUploadRequestBase(
          task_runner,
          CreateMultipartUploadMetadataJson(title,
                                            parent_resource_id,
                                            modified_date,
                                            last_viewed_by_me_date,
                                            properties),
          content_type,
          content_length,
          local_file_path,
          callback,
          progress_callback),
      resource_id_(resource_id),
      etag_(etag),
      has_modified_date_(!modified_date.is_null()),
      url_generator_(url_generator) {}

MultipartUploadExistingFileDelegate::~MultipartUploadExistingFileDelegate() {
}

std::vector<std::string>
MultipartUploadExistingFileDelegate::GetExtraRequestHeaders() const {
  std::vector<std::string> headers(
      MultipartUploadRequestBase::GetExtraRequestHeaders());
  headers.push_back(util::GenerateIfMatchHeader(etag_));
  return headers;
}

GURL MultipartUploadExistingFileDelegate::GetURL() const {
  return url_generator_.GetMultipartUploadExistingFileUrl(resource_id_,
                                                          has_modified_date_);
}

net::URLFetcher::RequestType
MultipartUploadExistingFileDelegate::GetRequestType() const {
  return net::URLFetcher::PUT;
}

//========================== DownloadFileRequest ==========================

DownloadFileRequest::DownloadFileRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const std::string& resource_id,
    const base::FilePath& output_file_path,
    const DownloadActionCallback& download_action_callback,
    const GetContentCallback& get_content_callback,
    const ProgressCallback& progress_callback)
    : DownloadFileRequestBase(
          sender,
          download_action_callback,
          get_content_callback,
          progress_callback,
          url_generator.GenerateDownloadFileUrl(resource_id),
          output_file_path) {
}

DownloadFileRequest::~DownloadFileRequest() {
}

//========================== PermissionsInsertRequest ==========================

PermissionsInsertRequest::PermissionsInsertRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator,
    const EntryActionCallback& callback)
    : EntryActionRequest(sender, callback),
      url_generator_(url_generator),
      type_(PERMISSION_TYPE_USER),
      role_(PERMISSION_ROLE_READER) {
}

PermissionsInsertRequest::~PermissionsInsertRequest() {
}

GURL PermissionsInsertRequest::GetURL() const {
  return url_generator_.GetPermissionsInsertUrl(id_);
}

net::URLFetcher::RequestType
PermissionsInsertRequest::GetRequestType() const {
  return net::URLFetcher::POST;
}

bool PermissionsInsertRequest::GetContentData(std::string* upload_content_type,
                                              std::string* upload_content) {
  *upload_content_type = util::kContentTypeApplicationJson;

  base::DictionaryValue root;
  switch (type_) {
    case PERMISSION_TYPE_ANYONE:
      root.SetString("type", "anyone");
      break;
    case PERMISSION_TYPE_DOMAIN:
      root.SetString("type", "domain");
      break;
    case PERMISSION_TYPE_GROUP:
      root.SetString("type", "group");
      break;
    case PERMISSION_TYPE_USER:
      root.SetString("type", "user");
      break;
  }
  switch (role_) {
    case PERMISSION_ROLE_OWNER:
      root.SetString("role", "owner");
      break;
    case PERMISSION_ROLE_READER:
      root.SetString("role", "reader");
      break;
    case PERMISSION_ROLE_WRITER:
      root.SetString("role", "writer");
      break;
    case PERMISSION_ROLE_COMMENTER:
      root.SetString("role", "reader");
      {
        base::ListValue* list = new base::ListValue;
        list->AppendString("commenter");
        root.Set("additionalRoles", list);
      }
      break;
  }
  root.SetString("value", value_);
  base::JSONWriter::Write(root, upload_content);
  return true;
}

//======================= SingleBatchableDelegateRequest =======================

SingleBatchableDelegateRequest::SingleBatchableDelegateRequest(
    RequestSender* sender,
    BatchableDelegate* delegate)
    : UrlFetchRequestBase(sender),
      delegate_(delegate),
      weak_ptr_factory_(this) {
}

SingleBatchableDelegateRequest::~SingleBatchableDelegateRequest() {
}

GURL SingleBatchableDelegateRequest::GetURL() const {
  return delegate_->GetURL();
}

net::URLFetcher::RequestType SingleBatchableDelegateRequest::GetRequestType()
    const {
  return delegate_->GetRequestType();
}

std::vector<std::string>
SingleBatchableDelegateRequest::GetExtraRequestHeaders() const {
  return delegate_->GetExtraRequestHeaders();
}

void SingleBatchableDelegateRequest::Prepare(const PrepareCallback& callback) {
  delegate_->Prepare(callback);
}

bool SingleBatchableDelegateRequest::GetContentData(
    std::string* upload_content_type,
    std::string* upload_content) {
  return delegate_->GetContentData(upload_content_type, upload_content);
}

void SingleBatchableDelegateRequest::ProcessURLFetchResults(
    const net::URLFetcher* source) {
  delegate_->NotifyResult(
      GetErrorCode(), response_writer()->data(),
      base::Bind(
          &SingleBatchableDelegateRequest::OnProcessURLFetchResultsComplete,
          weak_ptr_factory_.GetWeakPtr()));
}

void SingleBatchableDelegateRequest::RunCallbackOnPrematureFailure(
    DriveApiErrorCode code) {
  delegate_->NotifyError(code);
}

void SingleBatchableDelegateRequest::OnURLFetchUploadProgress(
    const net::URLFetcher* source,
    int64_t current,
    int64_t total) {
  delegate_->NotifyUploadProgress(source, current, total);
}

//========================== BatchUploadRequest ==========================

BatchUploadChildEntry::BatchUploadChildEntry(BatchableDelegate* request)
    : request(request), prepared(false), data_offset(0), data_size(0) {
}

BatchUploadChildEntry::~BatchUploadChildEntry() {
}

BatchUploadRequest::BatchUploadRequest(
    RequestSender* sender,
    const DriveApiUrlGenerator& url_generator)
    : UrlFetchRequestBase(sender),
      sender_(sender),
      url_generator_(url_generator),
      committed_(false),
      last_progress_value_(0),
      weak_ptr_factory_(this) {
}

BatchUploadRequest::~BatchUploadRequest() {
}

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

void BatchUploadRequest::AddRequest(BatchableDelegate* request) {
  DCHECK(CalledOnValidThread());
  DCHECK(request);
  DCHECK(GetChildEntry(request) == child_requests_.end());
  DCHECK(!committed_);
  child_requests_.push_back(new BatchUploadChildEntry(request));
  request->Prepare(base::Bind(&BatchUploadRequest::OnChildRequestPrepared,
                              weak_ptr_factory_.GetWeakPtr(), request));
}

void BatchUploadRequest::OnChildRequestPrepared(RequestID request_id,
                                                DriveApiErrorCode result) {
  DCHECK(CalledOnValidThread());
  auto const child = GetChildEntry(request_id);
  DCHECK(child != child_requests_.end());
  if (IsSuccessfulDriveApiErrorCode(result)) {
    (*child)->prepared = true;
  } else {
    (*child)->request->NotifyError(result);
    child_requests_.erase(child);
  }
  MayCompletePrepare();
}

void BatchUploadRequest::Commit() {
  DCHECK(CalledOnValidThread());
  DCHECK(!committed_);
  if (child_requests_.empty()) {
    Cancel();
  } else {
    committed_ = true;
    MayCompletePrepare();
  }
}

void BatchUploadRequest::Prepare(const PrepareCallback& callback) {
  DCHECK(CalledOnValidThread());
  DCHECK(!callback.is_null());
  prepare_callback_ = callback;
  MayCompletePrepare();
}

void BatchUploadRequest::Cancel() {
  child_requests_.clear();
  UrlFetchRequestBase::Cancel();
}

// Obtains corresponding child entry of |request_id|. Returns NULL if the
// entry is not found.
ScopedVector<BatchUploadChildEntry>::iterator BatchUploadRequest::GetChildEntry(
    RequestID request_id) {
  for (auto it = child_requests_.begin(); it != child_requests_.end(); ++it) {
    if ((*it)->request.get() == request_id)
      return it;
  }
  return child_requests_.end();
}

void BatchUploadRequest::MayCompletePrepare() {
  if (!committed_ || prepare_callback_.is_null())
    return;
  for (auto* child : child_requests_) {
    if (!child->prepared)
      return;
  }

  // Build multipart body here.
  int64_t total_size = 0;
  std::vector<ContentTypeAndData> parts;
  for (auto* child : child_requests_) {
    std::string type;
    std::string data;
    const bool result = child->request->GetContentData(&type, &data);
    // Upload request must have content data.
    DCHECK(result);

    const GURL url = child->request->GetURL();
    std::string method;
    switch (child->request->GetRequestType()) {
      case net::URLFetcher::POST:
        method = "POST";
        break;
      case net::URLFetcher::PUT:
        method = "PUT";
        break;
      default:
        NOTREACHED();
        break;
    }
    const std::string header = base::StringPrintf(
        kBatchUploadRequestFormat, method.c_str(), url.path().c_str(),
        url_generator_.GetBatchUploadUrl().host().c_str(), type.c_str());

    child->data_offset = header.size();
    child->data_size = data.size();
    total_size += data.size();

    parts.push_back(ContentTypeAndData({kHttpContentType, header + data}));
  }

  UMA_HISTOGRAM_COUNTS_100(kUMADriveTotalFileCountInBatchUpload, parts.size());
  UMA_HISTOGRAM_MEMORY_KB(kUMADriveTotalFileSizeInBatchUpload,
                          total_size / 1024);

  std::vector<uint64_t> part_data_offset;
  GenerateMultipartBody(MULTIPART_MIXED, boundary_, parts, &upload_content_,
                        &part_data_offset);
  DCHECK(part_data_offset.size() == child_requests_.size());
  for (size_t i = 0; i < child_requests_.size(); ++i) {
    child_requests_[i]->data_offset += part_data_offset[i];
  }
  prepare_callback_.Run(HTTP_SUCCESS);
}

bool BatchUploadRequest::GetContentData(std::string* upload_content_type,
                                        std::string* upload_content_data) {
  upload_content_type->assign(upload_content_.type);
  upload_content_data->assign(upload_content_.data);
  return true;
}

base::WeakPtr<BatchUploadRequest>
BatchUploadRequest::GetWeakPtrAsBatchUploadRequest() {
  return weak_ptr_factory_.GetWeakPtr();
}

GURL BatchUploadRequest::GetURL() const {
  return url_generator_.GetBatchUploadUrl();
}

net::URLFetcher::RequestType BatchUploadRequest::GetRequestType() const {
  return net::URLFetcher::PUT;
}

std::vector<std::string> BatchUploadRequest::GetExtraRequestHeaders() const {
  std::vector<std::string> headers;
  headers.push_back(kBatchUploadHeader);
  return headers;
}

void BatchUploadRequest::ProcessURLFetchResults(const net::URLFetcher* source) {
  // Return the detailed raw HTTP code if the error code is abstracted
  // DRIVE_OTHER_ERROR. If HTTP connection is failed and the status code is -1,
  // return network status error.
  int histogram_error = 0;
  if (GetErrorCode() != DRIVE_OTHER_ERROR) {
    histogram_error = GetErrorCode();
  } else if (source->GetResponseCode() != -1) {
    histogram_error = source->GetResponseCode();
  } else {
    histogram_error = source->GetStatus().error();
  }
  UMA_HISTOGRAM_SPARSE_SLOWLY(
      kUMADriveBatchUploadResponseCode, histogram_error);

  if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) {
    RunCallbackOnPrematureFailure(GetErrorCode());
    sender_->RequestFinished(this);
    return;
  }

  std::string content_type;
  source->GetResponseHeaders()->EnumerateHeader(
      /* need only first header */ NULL, "Content-Type", &content_type);

  std::vector<MultipartHttpResponse> parts;
  if (!ParseMultipartResponse(content_type, response_writer()->data(),
                              &parts) ||
      child_requests_.size() != parts.size()) {
    RunCallbackOnPrematureFailure(DRIVE_PARSE_ERROR);
    sender_->RequestFinished(this);
    return;
  }

  for (size_t i = 0; i < parts.size(); ++i) {
    BatchableDelegate* delegate = child_requests_[i]->request.get();
    // Pass ownership of |delegate| so that child_requests_.clear() won't
    // kill the delegate. It has to be deleted after the notification.
    delegate->NotifyResult(parts[i].code, parts[i].body,
                           base::Bind(&base::DeletePointer<BatchableDelegate>,
                                      child_requests_[i]->request.release()));
  }
  child_requests_.clear();

  sender_->RequestFinished(this);
}

void BatchUploadRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) {
  for (auto* child : child_requests_)
    child->request->NotifyError(code);
  child_requests_.clear();
}

void BatchUploadRequest::OnURLFetchUploadProgress(const net::URLFetcher* source,
                                                  int64_t current,
                                                  int64_t total) {
  for (auto* child : child_requests_) {
    if (child->data_offset <= current &&
        current <= child->data_offset + child->data_size) {
      child->request->NotifyUploadProgress(source, current - child->data_offset,
                                           child->data_size);
    } else if (last_progress_value_ < child->data_offset + child->data_size &&
               child->data_offset + child->data_size < current) {
      child->request->NotifyUploadProgress(source, child->data_size,
                                           child->data_size);
    }
  }
  last_progress_value_ = current;
}
}  // namespace drive
}  // namespace google_apis
