// 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 "components/drive/service/drive_api_service.h"

#include <stddef.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "components/drive/drive_api_util.h"
#include "google_apis/drive/auth_service.h"
#include "google_apis/drive/base_requests.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/drive_api_requests.h"
#include "google_apis/drive/drive_switches.h"
#include "google_apis/drive/files_list_request_runner.h"
#include "google_apis/drive/request_sender.h"
#include "google_apis/google_api_keys.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

using google_apis::AboutResourceCallback;
using google_apis::AppList;
using google_apis::AppListCallback;
using google_apis::AuthStatusCallback;
using google_apis::AuthorizeAppCallback;
using google_apis::CancelCallback;
using google_apis::ChangeList;
using google_apis::ChangeListCallback;
using google_apis::DRIVE_OTHER_ERROR;
using google_apis::DRIVE_PARSE_ERROR;
using google_apis::DownloadActionCallback;
using google_apis::DriveApiErrorCode;
using google_apis::EntryActionCallback;
using google_apis::FileList;
using google_apis::FileListCallback;
using google_apis::FileResource;
using google_apis::FileResourceCallback;
using google_apis::FilesListCorpora;
using google_apis::FilesListRequestRunner;
using google_apis::GetContentCallback;
using google_apis::GetShareUrlCallback;
using google_apis::HTTP_NOT_IMPLEMENTED;
using google_apis::HTTP_SUCCESS;
using google_apis::InitiateUploadCallback;
using google_apis::ProgressCallback;
using google_apis::RequestSender;
using google_apis::StartPageTokenCallback;
using google_apis::TeamDriveListCallback;
using google_apis::UploadRangeResponse;
using google_apis::drive::AboutGetRequest;
using google_apis::drive::AppsListRequest;
using google_apis::drive::ChangesListNextPageRequest;
using google_apis::drive::ChangesListRequest;
using google_apis::drive::ChildrenDeleteRequest;
using google_apis::drive::ChildrenInsertRequest;
using google_apis::drive::DownloadFileRequest;
using google_apis::drive::FilesCopyRequest;
using google_apis::drive::FilesDeleteRequest;
using google_apis::drive::FilesGetRequest;
using google_apis::drive::FilesInsertRequest;
using google_apis::drive::FilesListNextPageRequest;
using google_apis::drive::FilesListRequest;
using google_apis::drive::FilesPatchRequest;
using google_apis::drive::FilesTrashRequest;
using google_apis::drive::GetUploadStatusRequest;
using google_apis::drive::InitiateUploadExistingFileRequest;
using google_apis::drive::InitiateUploadNewFileRequest;
using google_apis::drive::ResumeUploadRequest;
using google_apis::drive::StartPageTokenRequest;
using google_apis::drive::TeamDriveListRequest;
using google_apis::drive::UploadRangeCallback;

namespace drive {

namespace {

// OAuth2 scopes for Drive API.
const char kDriveScope[] = "https://www.googleapis.com/auth/drive";
const char kDriveAppsReadonlyScope[] =
    "https://www.googleapis.com/auth/drive.apps.readonly";
const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
const char kDocsListScope[] = "https://docs.google.com/feeds/";

// Mime type to create a directory.
const char kFolderMimeType[] = "application/vnd.google-apps.folder";

// Max number of Team Drive entries to be fetched in a single http request.
const int kMaxNumTeamDriveResourcePerRequest = 100;

// Max number of file entries to be fetched in a single http request.
//
// The larger the number is,
// - The total running time to fetch the whole file list will become shorter.
// - The running time for a single request tends to become longer.
// Since the file list fetching is a completely background task, for our side,
// only the total time matters. However, the server seems to have a time limit
// per single request, which disables us to set the largest value (1000).
// TODO(kinaba): make it larger when the server gets faster.
const int kMaxNumFilesResourcePerRequest = 300;
const int kMaxNumFilesResourcePerRequestForSearch = 100;

// For performance, we declare all fields we use.
const char kAboutResourceFields[] =
    "kind,quotaBytesTotal,quotaBytesUsedAggregate,largestChangeId,rootFolderId";
const char kFileResourceFields[] =
    "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
    "md5Checksum,fileSize,labels/trashed,labels/starred,"
    "imageMediaMetadata/width,"
    "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
    "parents(id,parentLink),alternateLink,"
    "modifiedDate,lastViewedByMeDate,shared,modifiedByMeDate";
const char kFileResourceOpenWithLinksFields[] =
    "kind,id,openWithLinks/*";
const char kFileResourceShareLinkFields[] =
    "kind,id,shareLink";
const char kFileListFields[] =
    "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
    "mimeType,md5Checksum,fileSize,labels/trashed,labels/starred,"
    "imageMediaMetadata/width,"
    "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
    "parents(id,parentLink),alternateLink,"
    "modifiedDate,lastViewedByMeDate,shared,modifiedByMeDate,capabilities),"
    "nextLink";
const char kChangeListFields[] =
    "kind,items(type,file(kind,id,title,createdDate,sharedWithMeDate,"
    "mimeType,md5Checksum,fileSize,labels/trashed,labels/starred,"
    "imageMediaMetadata/width,"
    "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
    "parents(id,parentLink),alternateLink,modifiedDate,"
    "lastViewedByMeDate,shared,modifiedByMeDate,capabilities),"
    "teamDrive(kind,id,name,capabilities),teamDriveId,"
    "deleted,id,fileId,modificationDate),nextLink,"
    "largestChangeId,newStartPageToken";
const char kTeamDrivesListFields[] =
    "nextPageToken,kind,items(kind,id,name,capabilities)";

void ExtractOpenUrlAndRun(const std::string& app_id,
                          const AuthorizeAppCallback& callback,
                          DriveApiErrorCode error,
                          std::unique_ptr<FileResource> value) {
  DCHECK(!callback.is_null());

  if (!value) {
    callback.Run(error, GURL());
    return;
  }

  const std::vector<FileResource::OpenWithLink>& open_with_links =
      value->open_with_links();
  for (size_t i = 0; i < open_with_links.size(); ++i) {
    if (open_with_links[i].app_id == app_id) {
      callback.Run(HTTP_SUCCESS, open_with_links[i].open_url);
      return;
    }
  }

  // Not found.
  callback.Run(DRIVE_OTHER_ERROR, GURL());
}

void ExtractShareUrlAndRun(const GetShareUrlCallback& callback,
                           DriveApiErrorCode error,
                           std::unique_ptr<FileResource> value) {
  callback.Run(error, value ? value->share_link() : GURL());
}

// Ignores the |entry|, and runs the |callback|.
void EntryActionCallbackAdapter(const EntryActionCallback& callback,
                                DriveApiErrorCode error,
                                std::unique_ptr<FileResource> entry) {
  callback.Run(error);
}

// The resource ID for the root directory for Drive API is defined in the spec:
// https://developers.google.com/drive/folder
const char kDriveApiRootDirectoryResourceId[] = "root";

}  // namespace

BatchRequestConfigurator::BatchRequestConfigurator(
    const base::WeakPtr<google_apis::drive::BatchUploadRequest>& batch_request,
    base::SequencedTaskRunner* task_runner,
    const google_apis::DriveApiUrlGenerator& url_generator,
    const google_apis::CancelCallback& cancel_callback)
    : batch_request_(batch_request),
      task_runner_(task_runner),
      url_generator_(url_generator),
      cancel_callback_(cancel_callback) {
}

BatchRequestConfigurator::~BatchRequestConfigurator() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // The batch requst has not been committed.
  if (batch_request_)
    cancel_callback_.Run();
}

google_apis::CancelCallback BatchRequestConfigurator::MultipartUploadNewFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& parent_resource_id,
    const std::string& title,
    const base::FilePath& local_file_path,
    const UploadNewFileOptions& options,
    const google_apis::FileResourceCallback& callback,
    const google_apis::ProgressCallback& progress_callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!callback.is_null());

  std::unique_ptr<google_apis::BatchableDelegate> delegate(
      new google_apis::drive::MultipartUploadNewFileDelegate(
          task_runner_.get(), title, parent_resource_id, content_type,
          content_length, options.modified_date, options.last_viewed_by_me_date,
          local_file_path, options.properties, url_generator_, callback,
          progress_callback));
  // Batch request can be null when pre-authorization for the requst is failed
  // in request sender.
  if (batch_request_)
    batch_request_->AddRequest(delegate.release());
  else
    delegate->NotifyError(DRIVE_OTHER_ERROR);
  return cancel_callback_;
}

google_apis::CancelCallback
BatchRequestConfigurator::MultipartUploadExistingFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& resource_id,
    const base::FilePath& local_file_path,
    const UploadExistingFileOptions& options,
    const google_apis::FileResourceCallback& callback,
    const google_apis::ProgressCallback& progress_callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!callback.is_null());

  std::unique_ptr<google_apis::BatchableDelegate> delegate(
      new google_apis::drive::MultipartUploadExistingFileDelegate(
          task_runner_.get(), options.title, resource_id,
          options.parent_resource_id, content_type, content_length,
          options.modified_date, options.last_viewed_by_me_date,
          local_file_path, options.etag, options.properties, url_generator_,
          callback, progress_callback));
  // Batch request can be null when pre-authorization for the requst is failed
  // in request sender.
  if (batch_request_)
    batch_request_->AddRequest(delegate.release());
  else
    delegate->NotifyError(DRIVE_OTHER_ERROR);
  return cancel_callback_;
}

void BatchRequestConfigurator::Commit() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!batch_request_)
    return;
  batch_request_->Commit();
  batch_request_.reset();
}

DriveAPIService::DriveAPIService(
    OAuth2TokenService* oauth2_token_service,
    net::URLRequestContextGetter* url_request_context_getter,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    base::SequencedTaskRunner* blocking_task_runner,
    const GURL& base_url,
    const GURL& base_thumbnail_url,
    const std::string& custom_user_agent,
    const net::NetworkTrafficAnnotationTag& traffic_annotation)
    : oauth2_token_service_(oauth2_token_service),
      url_request_context_getter_(url_request_context_getter),
      url_loader_factory_(url_loader_factory),
      blocking_task_runner_(blocking_task_runner),
      url_generator_(base_url,
                     base_thumbnail_url,
                     google_apis::GetTeamDrivesIntegrationSwitch()),
      custom_user_agent_(custom_user_agent),
      traffic_annotation_(traffic_annotation) {}

DriveAPIService::~DriveAPIService() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (sender_)
    sender_->auth_service()->RemoveObserver(this);
}

void DriveAPIService::Initialize(const std::string& account_id) {
  DCHECK(thread_checker_.CalledOnValidThread());

  std::vector<std::string> scopes;
  scopes.push_back(kDriveScope);
  scopes.push_back(kDriveAppsReadonlyScope);
  scopes.push_back(kDriveAppsScope);

  // Note: The following scope is used to support GetShareUrl on Drive API v2.
  // Unfortunately, there is no support on Drive API v2, so we need to fall back
  // to GData WAPI for the GetShareUrl.
  scopes.push_back(kDocsListScope);

  sender_ = std::make_unique<RequestSender>(
      new google_apis::AuthService(oauth2_token_service_, account_id,
                                   url_loader_factory_, scopes),
      url_request_context_getter_.get(), blocking_task_runner_.get(),
      custom_user_agent_, traffic_annotation_);
  sender_->auth_service()->AddObserver(this);

  files_list_request_runner_ =
      std::make_unique<FilesListRequestRunner>(sender_.get(), url_generator_);
}

void DriveAPIService::AddObserver(DriveServiceObserver* observer) {
  observers_.AddObserver(observer);
}

void DriveAPIService::RemoveObserver(DriveServiceObserver* observer) {
  observers_.RemoveObserver(observer);
}

bool DriveAPIService::CanSendRequest() const {
  DCHECK(thread_checker_.CalledOnValidThread());

  return HasRefreshToken();
}

std::string DriveAPIService::GetRootResourceId() const {
  return kDriveApiRootDirectoryResourceId;
}

CancelCallback DriveAPIService::GetAllTeamDriveList(
    const TeamDriveListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<TeamDriveListRequest> request =
      std::make_unique<TeamDriveListRequest>(sender_.get(), url_generator_,
                                             callback);
  request->set_max_results(kMaxNumTeamDriveResourcePerRequest);
  request->set_fields(kTeamDrivesListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetAllFileList(
    const std::string& team_drive_id,
    const FileListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesListRequest> request =
      std::make_unique<FilesListRequest>(sender_.get(), url_generator_,
                                         callback);
  request->set_max_results(kMaxNumFilesResourcePerRequest);
  request->set_q("trashed = false");  // Exclude trashed files.
  request->set_fields(kFileListFields);
  if (team_drive_id.empty()) {
    request->set_corpora(google_apis::FilesListCorpora::DEFAULT);
  } else {
    request->set_team_drive_id(team_drive_id);
    request->set_corpora(google_apis::FilesListCorpora::TEAM_DRIVE);
  }
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetFileListInDirectory(
    const std::string& directory_resource_id,
    const FileListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!directory_resource_id.empty());
  DCHECK(!callback.is_null());

  // TODO(yamaguchi): Use FileListScope::CreateForTeamDrive instead of
  // kAllTeamDrives for efficiency. It'll require to add a new parameter to tell
  // which team drive the directory resource belongs to.
  FilesListCorpora corpora =
      (google_apis::GetTeamDrivesIntegrationSwitch() ==
       google_apis::TEAM_DRIVES_INTEGRATION_ENABLED)
          ? google_apis::FilesListCorpora::ALL_TEAM_DRIVES
          : google_apis::FilesListCorpora::DEFAULT;

  // Because children.list method on Drive API v2 returns only the list of
  // children's references, but we need all file resource list.
  // So, here we use files.list method instead, with setting parents query.
  // After the migration from GData WAPI to Drive API v2, we should clean the
  // code up by moving the responsibility to include "parents" in the query
  // to client side.
  // We aren't interested in files in trash in this context, neither.
  return files_list_request_runner_->CreateAndStartWithSizeBackoff(
      kMaxNumFilesResourcePerRequest, corpora, std::string(),
      base::StringPrintf(
          "'%s' in parents and trashed = false",
          util::EscapeQueryStringValue(directory_resource_id).c_str()),
      kFileListFields, callback);
}

CancelCallback DriveAPIService::Search(
    const std::string& search_query,
    const FileListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!search_query.empty());
  DCHECK(!callback.is_null());

  FilesListCorpora corpora =
      (google_apis::GetTeamDrivesIntegrationSwitch() ==
       google_apis::TEAM_DRIVES_INTEGRATION_ENABLED)
          ? google_apis::FilesListCorpora::ALL_TEAM_DRIVES
          : google_apis::FilesListCorpora::DEFAULT;

  std::string query = util::TranslateQuery(search_query);
  if (!query.empty())
    query += " and ";
  query += "trashed = false";

  return files_list_request_runner_->CreateAndStartWithSizeBackoff(
      kMaxNumFilesResourcePerRequestForSearch, corpora, std::string(), query,
      kFileListFields, callback);
}

CancelCallback DriveAPIService::SearchByTitle(
    const std::string& title,
    const std::string& directory_resource_id,
    const FileListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!title.empty());
  DCHECK(!callback.is_null());

  std::string query;
  base::StringAppendF(&query, "title = '%s'",
                      util::EscapeQueryStringValue(title).c_str());
  if (!directory_resource_id.empty()) {
    base::StringAppendF(
        &query, " and '%s' in parents",
        util::EscapeQueryStringValue(directory_resource_id).c_str());
  }
  query += " and trashed = false";

  std::unique_ptr<FilesListRequest> request =
      std::make_unique<FilesListRequest>(sender_.get(), url_generator_,
                                         callback);
  request->set_max_results(kMaxNumFilesResourcePerRequest);
  request->set_q(query);
  request->set_fields(kFileListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetChangeList(
    int64_t start_changestamp,
    const ChangeListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<ChangesListRequest> request =
      std::make_unique<ChangesListRequest>(sender_.get(), url_generator_,
                                           callback);
  request->set_max_results(kMaxNumFilesResourcePerRequest);
  request->set_start_change_id(start_changestamp);
  request->set_fields(kChangeListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetChangeListByToken(
    const std::string& team_drive_id,
    const std::string& start_page_token,
    const ChangeListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<ChangesListRequest> request =
      std::make_unique<ChangesListRequest>(sender_.get(), url_generator_,
                                           callback);
  request->set_max_results(kMaxNumFilesResourcePerRequest);
  request->set_page_token(start_page_token);
  request->set_team_drive_id(team_drive_id);
  request->set_fields(kChangeListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetRemainingChangeList(
    const GURL& next_link,
    const ChangeListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!next_link.is_empty());
  DCHECK(!callback.is_null());

  std::unique_ptr<ChangesListNextPageRequest> request =
      std::make_unique<ChangesListNextPageRequest>(sender_.get(), callback);
  request->set_next_link(next_link);
  request->set_fields(kChangeListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetRemainingTeamDriveList(
    const std::string& page_token,
    const TeamDriveListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!page_token.empty());
  DCHECK(!callback.is_null());

  std::unique_ptr<TeamDriveListRequest> request =
      std::make_unique<TeamDriveListRequest>(sender_.get(), url_generator_,
                                             callback);
  request->set_page_token(page_token);
  request->set_fields(kTeamDrivesListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetRemainingFileList(
    const GURL& next_link,
    const FileListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!next_link.is_empty());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesListNextPageRequest> request =
      std::make_unique<FilesListNextPageRequest>(sender_.get(), callback);
  request->set_next_link(next_link);
  request->set_fields(kFileListFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetFileResource(
    const std::string& resource_id,
    const FileResourceCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesGetRequest> request = std::make_unique<FilesGetRequest>(
      sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
      callback);
  request->set_file_id(resource_id);
  request->set_fields(kFileResourceFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetShareUrl(
    const std::string& resource_id,
    const GURL& embed_origin,
    const GetShareUrlCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (!google_apis::IsGoogleChromeAPIKeyUsed()) {
    LOG(ERROR) << "Only the official build of Chrome OS can open share dialogs "
               << "from the file manager.";
  }

  std::unique_ptr<FilesGetRequest> request = std::make_unique<FilesGetRequest>(
      sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
      base::Bind(&ExtractShareUrlAndRun, callback));
  request->set_file_id(resource_id);
  request->set_fields(kFileResourceShareLinkFields);
  request->set_embed_origin(embed_origin);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetAboutResource(
    const AboutResourceCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<AboutGetRequest> request = std::make_unique<AboutGetRequest>(
      sender_.get(), url_generator_, callback);
  request->set_fields(kAboutResourceFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetStartPageToken(
    const std::string& team_drive_id,
    const StartPageTokenCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<StartPageTokenRequest> request =
      std::make_unique<StartPageTokenRequest>(sender_.get(), url_generator_,
                                              callback);
  request->set_team_drive_id(team_drive_id);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::GetAppList(const AppListCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  return sender_->StartRequestWithAuthRetry(std::make_unique<AppsListRequest>(
      sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
      callback));
}

CancelCallback DriveAPIService::DownloadFile(
    const base::FilePath& local_cache_path,
    const std::string& resource_id,
    const DownloadActionCallback& download_action_callback,
    const GetContentCallback& get_content_callback,
    const ProgressCallback& progress_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!download_action_callback.is_null());
  // get_content_callback may be null.

  return sender_->StartRequestWithAuthRetry(
      std::make_unique<DownloadFileRequest>(
          sender_.get(), url_generator_, resource_id, local_cache_path,
          download_action_callback, get_content_callback, progress_callback));
}

CancelCallback DriveAPIService::DeleteResource(
    const std::string& resource_id,
    const std::string& etag,
    const EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesDeleteRequest> request =
      std::make_unique<FilesDeleteRequest>(sender_.get(), url_generator_,
                                           callback);
  request->set_file_id(resource_id);
  request->set_etag(etag);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::TrashResource(
    const std::string& resource_id,
    const EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesTrashRequest> request =
      std::make_unique<FilesTrashRequest>(
          sender_.get(), url_generator_,
          base::Bind(&EntryActionCallbackAdapter, callback));
  request->set_file_id(resource_id);
  request->set_fields(kFileResourceFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::AddNewDirectory(
    const std::string& parent_resource_id,
    const std::string& directory_title,
    const AddNewDirectoryOptions& options,
    const FileResourceCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesInsertRequest> request =
      std::make_unique<FilesInsertRequest>(sender_.get(), url_generator_,
                                           callback);
  request->set_visibility(options.visibility);
  request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  request->set_mime_type(kFolderMimeType);
  request->set_modified_date(options.modified_date);
  request->add_parent(parent_resource_id);
  request->set_title(directory_title);
  request->set_properties(options.properties);
  request->set_fields(kFileResourceFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::CopyResource(
    const std::string& resource_id,
    const std::string& parent_resource_id,
    const std::string& new_title,
    const base::Time& last_modified,
    const FileResourceCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesCopyRequest> request =
      std::make_unique<FilesCopyRequest>(sender_.get(), url_generator_,
                                         callback);
  request->set_file_id(resource_id);
  request->add_parent(parent_resource_id);
  request->set_title(new_title);
  request->set_modified_date(last_modified);
  request->set_fields(kFileResourceFields);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::UpdateResource(
    const std::string& resource_id,
    const std::string& parent_resource_id,
    const std::string& new_title,
    const base::Time& last_modified,
    const base::Time& last_viewed_by_me,
    const google_apis::drive::Properties& properties,
    const FileResourceCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<FilesPatchRequest> request =
      std::make_unique<FilesPatchRequest>(sender_.get(), url_generator_,
                                          callback);
  request->set_file_id(resource_id);
  request->set_title(new_title);
  if (!parent_resource_id.empty())
    request->add_parent(parent_resource_id);
  if (!last_modified.is_null()) {
    // Need to set setModifiedDate to true to overwrite modifiedDate.
    request->set_set_modified_date(true);
    request->set_modified_date(last_modified);
  }
  if (!last_viewed_by_me.is_null()) {
    // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
    // will be set to the request time (not the specified time via request).
    request->set_update_viewed_date(false);
    request->set_last_viewed_by_me_date(last_viewed_by_me);
  }
  request->set_fields(kFileResourceFields);
  request->set_properties(properties);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::AddResourceToDirectory(
    const std::string& parent_resource_id,
    const std::string& resource_id,
    const EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<ChildrenInsertRequest> request =
      std::make_unique<ChildrenInsertRequest>(sender_.get(), url_generator_,
                                              callback);
  request->set_folder_id(parent_resource_id);
  request->set_id(resource_id);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::RemoveResourceFromDirectory(
    const std::string& parent_resource_id,
    const std::string& resource_id,
    const EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<ChildrenDeleteRequest> request =
      std::make_unique<ChildrenDeleteRequest>(sender_.get(), url_generator_,
                                              callback);
  request->set_child_id(resource_id);
  request->set_folder_id(parent_resource_id);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::InitiateUploadNewFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& parent_resource_id,
    const std::string& title,
    const UploadNewFileOptions& options,
    const InitiateUploadCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<InitiateUploadNewFileRequest> request =
      std::make_unique<InitiateUploadNewFileRequest>(
          sender_.get(), url_generator_, content_type, content_length,
          parent_resource_id, title, callback);
  request->set_modified_date(options.modified_date);
  request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  request->set_properties(options.properties);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::InitiateUploadExistingFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& resource_id,
    const UploadExistingFileOptions& options,
    const InitiateUploadCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<InitiateUploadExistingFileRequest> request =
      std::make_unique<InitiateUploadExistingFileRequest>(
          sender_.get(), url_generator_, content_type, content_length,
          resource_id, options.etag, callback);
  request->set_parent_resource_id(options.parent_resource_id);
  request->set_title(options.title);
  request->set_modified_date(options.modified_date);
  request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  request->set_properties(options.properties);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

CancelCallback DriveAPIService::ResumeUpload(
    const GURL& upload_url,
    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) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  return sender_->StartRequestWithAuthRetry(
      std::make_unique<ResumeUploadRequest>(
          sender_.get(), upload_url, start_position, end_position,
          content_length, content_type, local_file_path, callback,
          progress_callback));
}

CancelCallback DriveAPIService::GetUploadStatus(
    const GURL& upload_url,
    int64_t content_length,
    const UploadRangeCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  return sender_->StartRequestWithAuthRetry(
      std::make_unique<GetUploadStatusRequest>(sender_.get(), upload_url,
                                               content_length, callback));
}

CancelCallback DriveAPIService::MultipartUploadNewFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& parent_resource_id,
    const std::string& title,
    const base::FilePath& local_file_path,
    const drive::UploadNewFileOptions& options,
    const FileResourceCallback& callback,
    const google_apis::ProgressCallback& progress_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  return sender_->StartRequestWithAuthRetry(
      std::make_unique<google_apis::drive::SingleBatchableDelegateRequest>(
          sender_.get(),
          std::make_unique<google_apis::drive::MultipartUploadNewFileDelegate>(
              sender_->blocking_task_runner(), title, parent_resource_id,
              content_type, content_length, options.modified_date,
              options.last_viewed_by_me_date, local_file_path,
              options.properties, url_generator_, callback,
              progress_callback)));
}

CancelCallback DriveAPIService::MultipartUploadExistingFile(
    const std::string& content_type,
    int64_t content_length,
    const std::string& resource_id,
    const base::FilePath& local_file_path,
    const drive::UploadExistingFileOptions& options,
    const FileResourceCallback& callback,
    const google_apis::ProgressCallback& progress_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  return sender_->StartRequestWithAuthRetry(
      std::make_unique<google_apis::drive::SingleBatchableDelegateRequest>(
          sender_.get(),
          std::make_unique<
              google_apis::drive::MultipartUploadExistingFileDelegate>(
              sender_->blocking_task_runner(), options.title, resource_id,
              options.parent_resource_id, content_type, content_length,
              options.modified_date, options.last_viewed_by_me_date,
              local_file_path, options.etag, options.properties, url_generator_,
              callback, progress_callback)));
}

CancelCallback DriveAPIService::AuthorizeApp(
    const std::string& resource_id,
    const std::string& app_id,
    const AuthorizeAppCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  // Files.Authorize is only available for whitelisted clients like official
  // Google Chrome. In other cases, we fall back to Files.Get that returns the
  // same value as Files.Authorize without doing authorization. In that case,
  // the app can open if it was authorized by other means (from whitelisted
  // clients or drive.google.com web UI.)
  if (google_apis::IsGoogleChromeAPIKeyUsed()) {
    std::unique_ptr<google_apis::drive::FilesAuthorizeRequest> request =
        std::make_unique<google_apis::drive::FilesAuthorizeRequest>(
            sender_.get(), url_generator_,
            base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
    request->set_app_id(app_id);
    request->set_file_id(resource_id);
    request->set_fields(kFileResourceOpenWithLinksFields);
    return sender_->StartRequestWithAuthRetry(std::move(request));
  } else {
    std::unique_ptr<FilesGetRequest> request =
        std::make_unique<FilesGetRequest>(
            sender_.get(), url_generator_,
            google_apis::IsGoogleChromeAPIKeyUsed(),
            base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
    request->set_file_id(resource_id);
    request->set_fields(kFileResourceOpenWithLinksFields);
    return sender_->StartRequestWithAuthRetry(std::move(request));
  }
}

CancelCallback DriveAPIService::UninstallApp(
    const std::string& app_id,
    const google_apis::EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<google_apis::drive::AppsDeleteRequest> request =
      std::make_unique<google_apis::drive::AppsDeleteRequest>(
          sender_.get(), url_generator_, callback);
  request->set_app_id(app_id);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

google_apis::CancelCallback DriveAPIService::AddPermission(
    const std::string& resource_id,
    const std::string& email,
    google_apis::drive::PermissionRole role,
    const google_apis::EntryActionCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::unique_ptr<google_apis::drive::PermissionsInsertRequest> request =
      std::make_unique<google_apis::drive::PermissionsInsertRequest>(
          sender_.get(), url_generator_, callback);
  request->set_id(resource_id);
  request->set_role(role);
  request->set_type(google_apis::drive::PERMISSION_TYPE_USER);
  request->set_value(email);
  return sender_->StartRequestWithAuthRetry(std::move(request));
}

bool DriveAPIService::HasAccessToken() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return sender_->auth_service()->HasAccessToken();
}

void DriveAPIService::RequestAccessToken(const AuthStatusCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  const std::string access_token = sender_->auth_service()->access_token();
  if (!access_token.empty()) {
    callback.Run(google_apis::HTTP_NOT_MODIFIED, access_token);
    return;
  }

  // Retrieve the new auth token.
  sender_->auth_service()->StartAuthentication(callback);
}

bool DriveAPIService::HasRefreshToken() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return sender_->auth_service()->HasRefreshToken();
}

void DriveAPIService::ClearAccessToken() {
  DCHECK(thread_checker_.CalledOnValidThread());
  sender_->auth_service()->ClearAccessToken();
}

void DriveAPIService::ClearRefreshToken() {
  DCHECK(thread_checker_.CalledOnValidThread());
  sender_->auth_service()->ClearRefreshToken();
}

void DriveAPIService::OnOAuth2RefreshTokenChanged() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (CanSendRequest()) {
    for (auto& observer : observers_)
      observer.OnReadyToSendRequests();
  } else if (!HasRefreshToken()) {
    for (auto& observer : observers_)
      observer.OnRefreshTokenInvalid();
  }
}

std::unique_ptr<BatchRequestConfiguratorInterface>
DriveAPIService::StartBatchRequest() {
  std::unique_ptr<google_apis::drive::BatchUploadRequest> request =
      std::make_unique<google_apis::drive::BatchUploadRequest>(sender_.get(),
                                                               url_generator_);
  const base::WeakPtr<google_apis::drive::BatchUploadRequest> weak_ref =
      request->GetWeakPtrAsBatchUploadRequest();
  // Have sender_ manage the lifetime of the request.
  // TODO(hirono): Currently we need to pass the ownership of the request to
  // RequestSender before the request is committed because the request has a
  // reference to RequestSender and we should ensure to delete the request when
  // the sender is deleted. Resolve the circulating dependency and fix it.
  const google_apis::CancelCallback callback =
      sender_->StartRequestWithAuthRetry(std::move(request));
  return std::make_unique<BatchRequestConfigurator>(
      weak_ref, sender_->blocking_task_runner(), url_generator_, callback);
}

}  // namespace drive
