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

#include <stddef.h>
#include <limits>
#include <map>
#include <set>
#include <utility>

#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "components/drive/chromeos/about_resource_loader.h"
#include "components/drive/chromeos/default_corpus_change_list_loader.h"
#include "components/drive/chromeos/drive_file_util.h"
#include "components/drive/chromeos/file_cache.h"
#include "components/drive/chromeos/file_system/copy_operation.h"
#include "components/drive/chromeos/file_system/create_directory_operation.h"
#include "components/drive/chromeos/file_system/create_file_operation.h"
#include "components/drive/chromeos/file_system/download_operation.h"
#include "components/drive/chromeos/file_system/get_file_for_saving_operation.h"
#include "components/drive/chromeos/file_system/move_operation.h"
#include "components/drive/chromeos/file_system/open_file_operation.h"
#include "components/drive/chromeos/file_system/remove_operation.h"
#include "components/drive/chromeos/file_system/search_operation.h"
#include "components/drive/chromeos/file_system/set_property_operation.h"
#include "components/drive/chromeos/file_system/touch_operation.h"
#include "components/drive/chromeos/file_system/truncate_operation.h"
#include "components/drive/chromeos/file_system_observer.h"
#include "components/drive/chromeos/loader_controller.h"
#include "components/drive/chromeos/remove_stale_cache_files.h"
#include "components/drive/chromeos/search_metadata.h"
#include "components/drive/chromeos/start_page_token_loader.h"
#include "components/drive/chromeos/sync_client.h"
#include "components/drive/drive.pb.h"
#include "components/drive/drive_pref_names.h"
#include "components/drive/file_change.h"
#include "components/drive/file_system_core_util.h"
#include "components/drive/job_scheduler.h"
#include "components/drive/resource_entry_conversion.h"
#include "google_apis/drive/drive_api_parser.h"

namespace drive {
namespace {

// Desired QPS for team drive background operations (update checking etc)
constexpr int kTeamDriveBackgroundOperationQPS = 10;

// Gets a ResourceEntry from the metadata, and overwrites its file info when the
// cached file is dirty.
FileError GetLocallyStoredResourceEntry(
    internal::ResourceMetadata* resource_metadata,
    internal::FileCache* cache,
    const base::FilePath& file_path,
    ResourceEntry* entry) {
  std::string local_id;
  FileError error = resource_metadata->GetIdByPath(file_path, &local_id);
  if (error != FILE_ERROR_OK)
    return error;

  error = resource_metadata->GetResourceEntryById(local_id, entry);
  if (error != FILE_ERROR_OK)
    return error;

  // For entries that will never be cached, use the original resource entry
  // as is.
  if (!entry->has_file_specific_info() ||
      entry->file_specific_info().is_hosted_document())
    return FILE_ERROR_OK;

  // When cache is not found, use the original resource entry as is.
  if (!entry->file_specific_info().has_cache_state())
    return FILE_ERROR_OK;

  // When cache is non-dirty and obsolete (old hash), use the original entry.
  if (!entry->file_specific_info().cache_state().is_dirty() &&
      entry->file_specific_info().md5() !=
      entry->file_specific_info().cache_state().md5())
    return FILE_ERROR_OK;

  // If there's a valid cache, obtain the file info from the cache file itself.
  base::FilePath local_cache_path;
  error = cache->GetFile(local_id, &local_cache_path);
  if (error != FILE_ERROR_OK)
    return error;

  base::File::Info file_info;
  if (!base::GetFileInfo(local_cache_path, &file_info))
    return FILE_ERROR_NOT_FOUND;

  entry->mutable_file_info()->set_size(file_info.size);
  return FILE_ERROR_OK;
}

// Runs the callback with parameters.
void RunGetResourceEntryCallback(GetResourceEntryCallback callback,
                                 std::unique_ptr<ResourceEntry> entry,
                                 FileError error) {
  DCHECK(callback);

  if (error != FILE_ERROR_OK)
    entry.reset();
  std::move(callback).Run(error, std::move(entry));
}

// Used to implement Pin().
FileError PinInternal(internal::ResourceMetadata* resource_metadata,
                      internal::FileCache* cache,
                      const base::FilePath& file_path,
                      std::string* local_id) {
  FileError error = resource_metadata->GetIdByPath(file_path, local_id);
  if (error != FILE_ERROR_OK)
    return error;

  ResourceEntry entry;
  error = resource_metadata->GetResourceEntryById(*local_id, &entry);
  if (error != FILE_ERROR_OK)
    return error;

  // TODO(hashimoto): Support pinning directories. crbug.com/127831
  if (entry.file_info().is_directory())
    return FILE_ERROR_NOT_A_FILE;

  return cache->Pin(*local_id);
}

// Used to implement Unpin().
FileError UnpinInternal(internal::ResourceMetadata* resource_metadata,
                        internal::FileCache* cache,
                        const base::FilePath& file_path,
                        std::string* local_id) {
  FileError error = resource_metadata->GetIdByPath(file_path, local_id);
  if (error != FILE_ERROR_OK)
    return error;

  return cache->Unpin(*local_id);
}

// Used to implement MarkCacheFileAsMounted().
FileError MarkCacheFileAsMountedInternal(
    internal::ResourceMetadata* resource_metadata,
    internal::FileCache* cache,
    const base::FilePath& drive_file_path,
    base::FilePath* cache_file_path) {
  std::string local_id;
  FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
  if (error != FILE_ERROR_OK)
    return error;

  return cache->MarkAsMounted(local_id, cache_file_path);
}

// Used to implement IsCacheFileMarkedAsMounted().
FileError IsCacheFileMarkedAsMountedInternal(
    internal::ResourceMetadata* resource_metadata,
    internal::FileCache* cache,
    const base::FilePath& drive_file_path,
    bool* result) {
  std::string local_id;
  FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
  if (error != FILE_ERROR_OK)
    return error;

  *result = cache->IsMarkedAsMounted(local_id);
  return FILE_ERROR_OK;
}

// Runs the callback with arguments.
void RunMarkMountedCallback(MarkMountedCallback callback,
                            base::FilePath* cache_file_path,
                            FileError error) {
  DCHECK(callback);
  std::move(callback).Run(error, *cache_file_path);
}

// Runs the callback with arguments.
void RunIsMountedCallback(IsMountedCallback callback,
                          bool* result,
                          FileError error) {
  DCHECK(callback);
  std::move(callback).Run(error, *result);
}

// Callback for internals::GetStartPageToken.
// |closure| must not be null.
void OnGetStartPageToken(const base::RepeatingClosure& closure,
                         FileError error) {
  DCHECK(closure);
  closure.Run();
}

// Thin adapter to map GetFileCallback to FileOperationCallback.
void GetFileCallbackToFileOperationCallbackAdapter(
    const FileOperationCallback& callback,
    FileError error,
    const base::FilePath& unused_file_path,
    std::unique_ptr<ResourceEntry> unused_entry) {
  callback.Run(error);
}

// Clears |resource_metadata| and |cache|.
FileError ResetOnBlockingPool(internal::ResourceMetadata* resource_metadata,
                              internal::FileCache* cache) {
  FileError error = resource_metadata->Reset();
  if (error != FILE_ERROR_OK)
    return error;
  return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED;
}

// Part of GetPathFromResourceId().
// Obtains |file_path| from |resource_id|. The function should be run on the
// blocking pool.
FileError GetPathFromResourceIdOnBlockingPool(
    internal::ResourceMetadata* resource_metadata,
    const std::string& resource_id,
    base::FilePath* file_path) {
  std::string local_id;
  const FileError error =
      resource_metadata->GetIdByResourceId(resource_id, &local_id);
  if (error != FILE_ERROR_OK)
    return error;
  return resource_metadata->GetFilePath(local_id, file_path);
}

// Part of GetPathFromResourceId().
// Called when GetPathFromResourceIdInBlockingPool is complete.
void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path,
                                       const GetFilePathCallback& callback,
                                       FileError error) {
  callback.Run(error, *file_path);
}

bool FreeDiskSpaceIfNeededForOnBlockingPool(internal::FileCache* cache,
                                            int64_t num_bytes) {
  return cache->FreeDiskSpaceIfNeededFor(num_bytes);
}

int64_t CalculateCacheSizeOnBlockingPool(internal::FileCache* cache) {
  return cache->CalculateCacheSize();
}

int64_t CalculateEvictableCacheSizeOnBlockingPool(internal::FileCache* cache) {
  return cache->CalculateEvictableCacheSize();
}

// Adapter for using FileOperationCallback as google_apis::EntryActionCallback.
void RunFileOperationCallbackAsEntryActionCallback(
    const FileOperationCallback& callback,
    google_apis::DriveApiErrorCode error) {
  callback.Run(GDataToFileError(error));
}

// Checks if the |entry|'s hash is included in |hashes|.
bool CheckHashes(const std::set<std::string>& hashes,
                 const ResourceEntry& entry) {
  return hashes.find(entry.file_specific_info().md5()) != hashes.end();
}

// Runs |callback| with |error| and the list of HashAndFilePath obtained from
// |original_result|.
void RunSearchByHashesCallback(
    SearchByHashesCallback callback,
    FileError error,
    std::unique_ptr<MetadataSearchResultVector> original_result) {
  std::vector<HashAndFilePath> result;
  if (error != FILE_ERROR_OK) {
    std::move(callback).Run(error, result);
    return;
  }
  for (const auto& search_result : *original_result) {
    HashAndFilePath hash_and_path;
    hash_and_path.hash = search_result.md5;
    hash_and_path.path = search_result.path;
    result.push_back(hash_and_path);
  }
  std::move(callback).Run(FILE_ERROR_OK, result);
}

}  // namespace

struct FileSystem::CreateDirectoryParams {
  base::FilePath directory_path;
  bool is_exclusive;
  bool is_recursive;
  FileOperationCallback callback;
};

FileSystem::FileSystem(EventLogger* logger,
                       internal::FileCache* cache,
                       JobScheduler* scheduler,
                       internal::ResourceMetadata* resource_metadata,
                       base::SequencedTaskRunner* blocking_task_runner,
                       const base::FilePath& temporary_file_directory,
                       const base::Clock* clock)
    : logger_(logger),
      cache_(cache),
      scheduler_(scheduler),
      resource_metadata_(resource_metadata),
      blocking_task_runner_(blocking_task_runner),
      temporary_file_directory_(temporary_file_directory),
      clock_(clock),
      weak_ptr_factory_(this) {
  ResetComponents();
}

FileSystem::~FileSystem() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  default_corpus_change_list_loader_->RemoveChangeListLoaderObserver(this);
  default_corpus_change_list_loader_->RemoveTeamDriveListObserver(this);
}

void FileSystem::Reset(const FileOperationCallback& callback) {
  // Discard the current loader and operation objects and renew them. This is to
  // avoid that changes initiated before the metadata reset is applied after the
  // reset, which may cause an inconsistent state.
  // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
  // want to have a way to abort and flush callbacks in in-flight operations.
  ResetComponents();

  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_),
      callback);
}

void FileSystem::ResetComponents() {
  file_system::OperationDelegate* delegate = this;

  about_resource_loader_ =
      std::make_unique<internal::AboutResourceLoader>(scheduler_);
  loader_controller_ = std::make_unique<internal::LoaderController>();

  default_corpus_change_list_loader_ =
      std::make_unique<internal::DefaultCorpusChangeListLoader>(
          logger_, blocking_task_runner_.get(), resource_metadata_, scheduler_,
          about_resource_loader_.get(), loader_controller_.get(), clock_);

  default_corpus_change_list_loader_->AddChangeListLoaderObserver(this);
  default_corpus_change_list_loader_->AddTeamDriveListObserver(this);

  sync_client_ = std::make_unique<internal::SyncClient>(
      blocking_task_runner_.get(), delegate, scheduler_, resource_metadata_,
      cache_, loader_controller_.get(), temporary_file_directory_);

  team_drive_operation_queue_ =
      std::make_unique<internal::DriveBackgroundOperationQueue<
          internal::TeamDriveChangeListLoader>>(
          kTeamDriveBackgroundOperationQPS);

  copy_operation_ = std::make_unique<file_system::CopyOperation>(
      blocking_task_runner_.get(), delegate, scheduler_, resource_metadata_,
      cache_);
  create_directory_operation_ =
      std::make_unique<file_system::CreateDirectoryOperation>(
          blocking_task_runner_.get(), delegate, resource_metadata_);
  create_file_operation_ = std::make_unique<file_system::CreateFileOperation>(
      blocking_task_runner_.get(), delegate, resource_metadata_);
  move_operation_ = std::make_unique<file_system::MoveOperation>(
      blocking_task_runner_.get(), delegate, resource_metadata_);
  open_file_operation_ = std::make_unique<file_system::OpenFileOperation>(
      blocking_task_runner_.get(), delegate, scheduler_, resource_metadata_,
      cache_, temporary_file_directory_);
  remove_operation_ = std::make_unique<file_system::RemoveOperation>(
      blocking_task_runner_.get(), delegate, resource_metadata_, cache_);
  touch_operation_ = std::make_unique<file_system::TouchOperation>(
      blocking_task_runner_.get(), delegate, resource_metadata_);
  truncate_operation_ = std::make_unique<file_system::TruncateOperation>(
      blocking_task_runner_.get(), delegate, scheduler_, resource_metadata_,
      cache_, temporary_file_directory_);
  download_operation_ = std::make_unique<file_system::DownloadOperation>(
      blocking_task_runner_.get(), delegate, scheduler_, resource_metadata_,
      cache_, temporary_file_directory_);
  search_operation_ = std::make_unique<file_system::SearchOperation>(
      blocking_task_runner_.get(), scheduler_, resource_metadata_,
      loader_controller_.get());
  get_file_for_saving_operation_ =
      std::make_unique<file_system::GetFileForSavingOperation>(

          logger_, blocking_task_runner_.get(), delegate, scheduler_,
          resource_metadata_, cache_, temporary_file_directory_);
  set_property_operation_ = std::make_unique<file_system::SetPropertyOperation>(
      blocking_task_runner_.get(), delegate, resource_metadata_);
}

void FileSystem::CheckForUpdates() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DVLOG(1) << "CheckForUpdates";

  size_t num_callbacks = team_drive_change_list_loaders_.size() + 1;

  base::RepeatingClosure closure = base::BarrierClosure(
      num_callbacks, base::BindOnce(&FileSystem::OnUpdateCompleted,
                                    weak_ptr_factory_.GetWeakPtr()));

  for (auto& team_drive : team_drive_change_list_loaders_) {
    auto update_checked_closure =
        base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr(),
                   team_drive.first, closure);
    if (!team_drive.second->IsRefreshing()) {
      team_drive_operation_queue_->AddOperation(
          team_drive.second->GetWeakPtr(),
          base::BindOnce(&internal::TeamDriveChangeListLoader::CheckForUpdates,
                         team_drive.second->GetWeakPtr()),
          update_checked_closure);
    } else {
      // If the change list loader is refreshing, then calling CheckForUpdates
      // will just add the callback to a queue to be called when the refresh
      // is complete.
      team_drive.second->CheckForUpdates(update_checked_closure);
    }
  }

  default_corpus_change_list_loader_->CheckForUpdates(
      base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr(),
                 std::string(), closure));
}

void FileSystem::CheckForUpdates(const std::set<std::string>& ids) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  base::RepeatingClosure closure = base::BarrierClosure(
      ids.size(), base::BindOnce(&FileSystem::OnUpdateCompleted,
                                 weak_ptr_factory_.GetWeakPtr()));

  for (const auto& id : ids) {
    if (id.empty()) {
      default_corpus_change_list_loader_->CheckForUpdates(
          base::Bind(&FileSystem::OnUpdateChecked,
                     weak_ptr_factory_.GetWeakPtr(), std::string(), closure));
    } else {
      auto it = team_drive_change_list_loaders_.find(id);

      // It is possible for the team drive to have been deleted by the time we
      // receive the push notification.
      if (it != team_drive_change_list_loaders_.end()) {
        auto update_checked_closure =
            base::Bind(&FileSystem::OnUpdateChecked,
                       weak_ptr_factory_.GetWeakPtr(), it->first, closure);
        if (!it->second->IsRefreshing()) {
          team_drive_operation_queue_->AddOperation(
              it->second->GetWeakPtr(),
              base::BindOnce(
                  &internal::TeamDriveChangeListLoader::CheckForUpdates,
                  it->second->GetWeakPtr()),
              update_checked_closure);
        } else {
          // If the change list loader is refreshing, then calling
          // CheckForUpdates will just add the callback to a queue to be called
          // when the refresh is complete.
          it->second->CheckForUpdates(update_checked_closure);
        }
      } else {
        closure.Run();
      }
    }
  }
}

void FileSystem::OnUpdateChecked(const std::string& team_drive_id,
                                 const base::RepeatingClosure& closure,
                                 FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error);

  last_update_metadata_[team_drive_id].last_update_check_error = error;
  last_update_metadata_[team_drive_id].last_update_check_time =
      base::Time::Now();
  closure.Run();
}

void FileSystem::OnUpdateCompleted() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}

void FileSystem::AddObserver(FileSystemObserver* observer) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  observers_.AddObserver(observer);
}

void FileSystem::RemoveObserver(FileSystemObserver* observer) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  observers_.RemoveObserver(observer);
}

void FileSystem::TransferFileFromLocalToRemote(
    const base::FilePath& local_src_file_path,
    const base::FilePath& remote_dest_file_path,
    const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  copy_operation_->TransferFileFromLocalToRemote(local_src_file_path,
                                                 remote_dest_file_path,
                                                 callback);
}

void FileSystem::Copy(const base::FilePath& src_file_path,
                      const base::FilePath& dest_file_path,
                      bool preserve_last_modified,
                      const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  copy_operation_->Copy(
      src_file_path, dest_file_path, preserve_last_modified, callback);
}

void FileSystem::Move(const base::FilePath& src_file_path,
                      const base::FilePath& dest_file_path,
                      const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  move_operation_->Move(src_file_path, dest_file_path, callback);
}

void FileSystem::Remove(const base::FilePath& file_path,
                        bool is_recursive,
                        const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  remove_operation_->Remove(file_path, is_recursive, callback);
}

void FileSystem::CreateDirectory(
    const base::FilePath& directory_path,
    bool is_exclusive,
    bool is_recursive,
    const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  CreateDirectoryParams params;
  params.directory_path = directory_path;
  params.is_exclusive = is_exclusive;
  params.is_recursive = is_recursive;
  params.callback = callback;

  // Ensure its parent directory is loaded to the local metadata.
  ReadDirectory(directory_path.DirName(),
                ReadDirectoryEntriesCallback(),
                base::Bind(&FileSystem::CreateDirectoryAfterRead,
                           weak_ptr_factory_.GetWeakPtr(), params));
}

void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams& params,
                                          FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(params.callback);

  DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
                                      << FileErrorToString(error);

  create_directory_operation_->CreateDirectory(
      params.directory_path, params.is_exclusive, params.is_recursive,
      params.callback);
}

void FileSystem::CreateFile(const base::FilePath& file_path,
                            bool is_exclusive,
                            const std::string& mime_type,
                            const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  create_file_operation_->CreateFile(
      file_path, is_exclusive, mime_type, callback);
}

void FileSystem::TouchFile(const base::FilePath& file_path,
                           const base::Time& last_access_time,
                           const base::Time& last_modified_time,
                           const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  touch_operation_->TouchFile(
      file_path, last_access_time, last_modified_time, callback);
}

void FileSystem::TruncateFile(const base::FilePath& file_path,
                              int64_t length,
                              const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  truncate_operation_->Truncate(file_path, length, callback);
}

void FileSystem::Pin(const base::FilePath& file_path,
                     const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  std::string* local_id = new std::string;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id),
      base::Bind(&FileSystem::FinishPin,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 base::Owned(local_id)));
}

void FileSystem::FinishPin(const FileOperationCallback& callback,
                           const std::string* local_id,
                           FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  if (error == FILE_ERROR_OK)
    sync_client_->AddFetchTask(*local_id);
  callback.Run(error);
}

void FileSystem::Unpin(const base::FilePath& file_path,
                       const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  std::string* local_id = new std::string;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(
          &UnpinInternal, resource_metadata_, cache_, file_path, local_id),
      base::Bind(&FileSystem::FinishUnpin,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 base::Owned(local_id)));
}

void FileSystem::FinishUnpin(const FileOperationCallback& callback,
                             const std::string* local_id,
                             FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  if (error == FILE_ERROR_OK)
    sync_client_->RemoveFetchTask(*local_id);
  callback.Run(error);
}

void FileSystem::GetFile(const base::FilePath& file_path,
                         GetFileCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  download_operation_->EnsureFileDownloadedByPath(
      file_path, ClientContext(USER_INITIATED),
      GetFileContentInitializedCallback(), google_apis::GetContentCallback(),
      std::move(callback));
}

void FileSystem::GetFileForSaving(const base::FilePath& file_path,
                                  GetFileCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  get_file_for_saving_operation_->GetFileForSaving(file_path,
                                                   std::move(callback));
}

base::Closure FileSystem::GetFileContent(
    const base::FilePath& file_path,
    GetFileContentInitializedCallback initialized_callback,
    const google_apis::GetContentCallback& get_content_callback,
    const FileOperationCallback& completion_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(initialized_callback);
  DCHECK(get_content_callback);
  DCHECK(completion_callback);

  return download_operation_->EnsureFileDownloadedByPath(
      file_path, ClientContext(USER_INITIATED), std::move(initialized_callback),
      get_content_callback,
      base::Bind(&GetFileCallbackToFileOperationCallbackAdapter,
                 completion_callback));
}

void FileSystem::GetResourceEntry(const base::FilePath& file_path,
                                  GetResourceEntryCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  ReadDirectory(file_path.DirName(), ReadDirectoryEntriesCallback(),
                base::Bind(&FileSystem::GetResourceEntryAfterRead,
                           weak_ptr_factory_.GetWeakPtr(), file_path,
                           base::Passed(std::move(callback))));
}

void FileSystem::GetResourceEntryAfterRead(const base::FilePath& file_path,
                                           GetResourceEntryCallback callback,
                                           FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
                                      << FileErrorToString(error);

  std::unique_ptr<ResourceEntry> entry(new ResourceEntry);
  ResourceEntry* entry_ptr = entry.get();
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::BindOnce(&GetLocallyStoredResourceEntry, resource_metadata_, cache_,
                     file_path, entry_ptr),
      base::BindOnce(&RunGetResourceEntryCallback, std::move(callback),
                     std::move(entry)));
}

void FileSystem::ReadDirectory(
    const base::FilePath& directory_path,
    ReadDirectoryEntriesCallback entries_callback,
    const FileOperationCallback& completion_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(completion_callback);

  if (util::GetDriveTeamDrivesRootPath().IsParent(directory_path)) {
    // If we do not match a single team drive then we will run the default
    // corpus loader to read the directory.
    for (auto& team_drive_loader : team_drive_change_list_loaders_) {
      const base::FilePath& team_drive_path =
          team_drive_loader.second->root_entry_path();
      if (team_drive_path == directory_path ||
          team_drive_path.IsParent(directory_path)) {
        team_drive_loader.second->ReadDirectory(
            directory_path, std::move(entries_callback), completion_callback);
        return;
      }
    }
  }
  // Fall through to the default corpus loader if no team drive loader is found.
  // We do not refresh the list of team drives from the server until the first
  // ReadDirectory is called on the default corpus change list loader.
  default_corpus_change_list_loader_->ReadDirectory(
      directory_path, std::move(entries_callback), completion_callback);
}

void FileSystem::GetAvailableSpace(GetAvailableSpaceCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  about_resource_loader_->GetAboutResource(base::Bind(
      &FileSystem::OnGetAboutResource, weak_ptr_factory_.GetWeakPtr(),
      base::Passed(std::move(callback))));
}

void FileSystem::OnGetAboutResource(
    GetAvailableSpaceCallback callback,
    google_apis::DriveApiErrorCode status,
    std::unique_ptr<google_apis::AboutResource> about_resource) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  FileError error = GDataToFileError(status);
  if (error != FILE_ERROR_OK) {
    std::move(callback).Run(error, -1, -1);
    return;
  }
  DCHECK(about_resource);

  std::move(callback).Run(FILE_ERROR_OK, about_resource->quota_bytes_total(),
                          about_resource->quota_bytes_used_aggregate());
}

void FileSystem::Search(const std::string& search_query,
                        const GURL& next_link,
                        SearchCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  search_operation_->Search(search_query, next_link, std::move(callback));
}

void FileSystem::SearchMetadata(const std::string& query,
                                int options,
                                int at_most_num_matches,
                                MetadataSearchOrder order,
                                SearchMetadataCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  drive::internal::SearchMetadata(
      blocking_task_runner_, resource_metadata_, query,
      base::Bind(&drive::internal::MatchesType, options), at_most_num_matches,
      order, std::move(callback));
}

void FileSystem::SearchByHashes(const std::set<std::string>& hashes,
                                SearchByHashesCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  drive::internal::SearchMetadata(
      blocking_task_runner_, resource_metadata_,
      /* any file name */ "", base::Bind(&CheckHashes, hashes),
      std::numeric_limits<size_t>::max(),
      drive::MetadataSearchOrder::LAST_ACCESSED,
      base::BindOnce(&RunSearchByHashesCallback, std::move(callback)));
}

void FileSystem::OnFileChangedByOperation(const FileChange& changed_files) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  for (auto& observer : observers_)
    observer.OnFileChanged(changed_files);
}

void FileSystem::OnEntryUpdatedByOperation(const ClientContext& context,
                                           const std::string& local_id) {
  sync_client_->AddUpdateTask(context, local_id);
}

void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type,
                                  const std::string& local_id) {
  base::FilePath* file_path = new base::FilePath;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&internal::ResourceMetadata::GetFilePath,
                 base::Unretained(resource_metadata_),
                 local_id,
                 file_path),
      base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath,
                 weak_ptr_factory_.GetWeakPtr(),
                 type,
                 base::Owned(file_path)));
}

void FileSystem::OnDriveSyncErrorAfterGetFilePath(
    file_system::DriveSyncErrorType type,
    const base::FilePath* file_path,
    FileError error) {
  if (error != FILE_ERROR_OK)
    return;
  for (auto& observer : observers_)
    observer.OnDriveSyncError(type, *file_path);
}

bool FileSystem::WaitForSyncComplete(const std::string& local_id,
                                     const FileOperationCallback& callback) {
  return sync_client_->WaitForUpdateTaskToComplete(local_id, callback);
}

void FileSystem::OnDirectoryReloaded(const base::FilePath& directory_path) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  for (auto& observer : observers_)
    observer.OnDirectoryChanged(directory_path);
}

void FileSystem::OnFileChanged(const FileChange& changed_files) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  for (auto& observer : observers_)
    observer.OnFileChanged(changed_files);
}

void FileSystem::OnTeamDrivesChanged(const FileChange& changed_team_drives) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  std::set<std::string> added_team_drives;
  std::set<std::string> removed_team_drives;

  for (const auto& entry : changed_team_drives.map()) {
    for (const auto& change : entry.second.list()) {
      DCHECK(!change.team_drive_id().empty());
      if (change.IsDelete()) {
        if (team_drive_change_list_loaders_.erase(change.team_drive_id()) > 0) {
          // If we were tracking the update status we can remove that as well.
          last_update_metadata_.erase(change.team_drive_id());
          removed_team_drives.insert(change.team_drive_id());
        }
      } else if (change.IsAddOrUpdate()) {
        // If this is an update (e.g. a renamed team drive), then just erase the
        // existing entry so we can re-add it with the new path.
        team_drive_change_list_loaders_.erase(change.team_drive_id());

        auto loader = std::make_unique<internal::TeamDriveChangeListLoader>(
            change.team_drive_id(), entry.first, logger_,
            blocking_task_runner_.get(), resource_metadata_, scheduler_,
            loader_controller_.get());
        loader->AddChangeListLoaderObserver(this);
        team_drive_operation_queue_->AddOperation(
            loader->GetWeakPtr(),
            base::BindOnce(&internal::TeamDriveChangeListLoader::LoadIfNeeded,
                           loader->GetWeakPtr()),
            base::DoNothing());
        team_drive_change_list_loaders_.emplace(change.team_drive_id(),
                                                std::move(loader));
        added_team_drives.insert(change.team_drive_id());
      }
    }
  }
  for (auto& observer : observers_) {
    observer.OnTeamDrivesUpdated(added_team_drives, removed_team_drives);
  }
}

void FileSystem::OnLoadFromServerComplete() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  sync_client_->StartCheckingExistingPinnedFiles();
}

void FileSystem::OnInitialLoadComplete() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&internal::RemoveStaleCacheFiles, cache_,
                                resource_metadata_));
  sync_client_->StartProcessingBacklog();
}

void FileSystem::OnTeamDriveListLoaded(
    const std::vector<internal::TeamDrive>& team_drives_list,
    const std::vector<internal::TeamDrive>& added_team_drives,
    const std::vector<internal::TeamDrive>& removed_team_drives) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  for (auto& team_drive_loader : team_drive_change_list_loaders_) {
    team_drive_loader.second->RemoveChangeListLoaderObserver(this);
  }
  team_drive_change_list_loaders_.clear();

  std::set<std::string> added_team_drives_ids;
  for (const auto& team_drive : team_drives_list) {
    auto loader = std::make_unique<internal::TeamDriveChangeListLoader>(
        team_drive.team_drive_id(), team_drive.team_drive_path(), logger_,
        blocking_task_runner_.get(), resource_metadata_, scheduler_,
        loader_controller_.get());
    loader->AddChangeListLoaderObserver(this);
    team_drive_operation_queue_->AddOperation(
        loader->GetWeakPtr(),
        base::BindOnce(&internal::TeamDriveChangeListLoader::LoadIfNeeded,
                       loader->GetWeakPtr()),
        base::DoNothing());
    team_drive_change_list_loaders_.emplace(team_drive.team_drive_id(),
                                            std::move(loader));
    added_team_drives_ids.insert(team_drive.team_drive_id());
  }
  for (auto& observer : observers_) {
    observer.OnTeamDrivesUpdated(added_team_drives_ids, {});
  }
}

void FileSystem::GetMetadata(GetFilesystemMetadataCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  FileSystemMetadata* metadata = new FileSystemMetadata();
  std::map<std::string, FileSystemMetadata>* team_drive_metadata =
      new std::map<std::string, FileSystemMetadata>();

  size_t num_callbacks = team_drive_change_list_loaders_.size() + 1;

  base::RepeatingClosure closure = base::BarrierClosure(
      num_callbacks,
      base::BindOnce(&FileSystem::OnGetMetadata, weak_ptr_factory_.GetWeakPtr(),
                     base::Passed(std::move(callback)), base::Owned(metadata),
                     base::Owned(team_drive_metadata)));

  metadata->refreshing = default_corpus_change_list_loader_->IsRefreshing();
  metadata->path = util::GetDriveGrandRootPath().value();
  metadata->last_update_check_time =
      last_update_metadata_[util::kTeamDriveIdDefaultCorpus]
          .last_update_check_time;
  metadata->last_update_check_error =
      last_update_metadata_[util::kTeamDriveIdDefaultCorpus]
          .last_update_check_error;

  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&internal::GetStartPageToken,
                 base::Unretained(resource_metadata_),
                 util::kTeamDriveIdDefaultCorpus,
                 base::Unretained(&(metadata->start_page_token))),
      base::Bind(&OnGetStartPageToken, closure));

  for (auto& team_drive : team_drive_change_list_loaders_) {
    const FileSystemMetadata& last_update_metadata =
        last_update_metadata_[team_drive.first];
    FileSystemMetadata& md = (*team_drive_metadata)[team_drive.first];

    md.refreshing = team_drive.second->IsRefreshing();
    md.path = team_drive.second->root_entry_path().value();
    md.last_update_check_time = last_update_metadata.last_update_check_time;
    md.last_update_check_error = last_update_metadata.last_update_check_error;

    base::PostTaskAndReplyWithResult(
        blocking_task_runner_.get(), FROM_HERE,
        base::Bind(&internal::GetStartPageToken,
                   base::Unretained(resource_metadata_), team_drive.first,
                   base::Unretained(&(md.start_page_token))),
        base::Bind(&OnGetStartPageToken, closure));
  }
}

void FileSystem::OnGetMetadata(
    GetFilesystemMetadataCallback callback,
    drive::FileSystemMetadata* default_corpus_metadata,
    std::map<std::string, drive::FileSystemMetadata>* team_drive_metadata) {
  DCHECK(callback);
  DCHECK(default_corpus_metadata);
  DCHECK(team_drive_metadata);

  std::move(callback).Run(*default_corpus_metadata, *team_drive_metadata);
}

void FileSystem::MarkCacheFileAsMounted(const base::FilePath& drive_file_path,
                                        MarkMountedCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  base::FilePath* cache_file_path = new base::FilePath;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::BindOnce(&MarkCacheFileAsMountedInternal, resource_metadata_,
                     cache_, drive_file_path, cache_file_path),
      base::BindOnce(&RunMarkMountedCallback, std::move(callback),
                     base::Owned(cache_file_path)));
}

void FileSystem::IsCacheFileMarkedAsMounted(
    const base::FilePath& drive_file_path,
    IsMountedCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  bool* is_mounted = new bool(false);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::BindOnce(&IsCacheFileMarkedAsMountedInternal, resource_metadata_,
                     cache_, drive_file_path, is_mounted),
      base::BindOnce(&RunIsMountedCallback, std::move(callback),
                     base::Owned(is_mounted)));
}

void FileSystem::MarkCacheFileAsUnmounted(
    const base::FilePath& cache_file_path,
    const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) {
    callback.Run(FILE_ERROR_FAILED);
    return;
  }

  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&internal::FileCache::MarkAsUnmounted,
                 base::Unretained(cache_),
                 cache_file_path),
      callback);
}

void FileSystem::AddPermission(const base::FilePath& drive_file_path,
                               const std::string& email,
                               google_apis::drive::PermissionRole role,
                               const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  // Resolve the resource id.
  ResourceEntry* const entry = new ResourceEntry;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
                 base::Unretained(resource_metadata_),
                 drive_file_path,
                 entry),
      base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry,
                 weak_ptr_factory_.GetWeakPtr(),
                 email,
                 role,
                 callback,
                 base::Owned(entry)));
}

void FileSystem::AddPermissionAfterGetResourceEntry(
    const std::string& email,
    google_apis::drive::PermissionRole role,
    const FileOperationCallback& callback,
    ResourceEntry* entry,
    FileError error) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (error != FILE_ERROR_OK) {
    callback.Run(error);
    return;
  }

  scheduler_->AddPermission(
      entry->resource_id(),
      email,
      role,
      base::Bind(&RunFileOperationCallbackAsEntryActionCallback, callback));
}

void FileSystem::SetProperty(
    const base::FilePath& drive_file_path,
    google_apis::drive::Property::Visibility visibility,
    const std::string& key,
    const std::string& value,
    const FileOperationCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  set_property_operation_->SetProperty(drive_file_path, visibility, key, value,
                                       callback);
}

void FileSystem::OpenFile(const base::FilePath& file_path,
                          OpenMode open_mode,
                          const std::string& mime_type,
                          OpenFileCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  open_file_operation_->OpenFile(file_path, open_mode, mime_type,
                                 std::move(callback));
}

void FileSystem::GetPathFromResourceId(const std::string& resource_id,
                                       const GetFilePathCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);

  base::FilePath* const file_path = new base::FilePath();
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&GetPathFromResourceIdOnBlockingPool,
                 resource_metadata_,
                 resource_id,
                 file_path),
      base::Bind(&GetPathFromResourceIdAfterGetPath,
                 base::Owned(file_path),
                 callback));
}

void FileSystem::FreeDiskSpaceIfNeededFor(
    int64_t num_bytes,
    const FreeDiskSpaceCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&FreeDiskSpaceIfNeededForOnBlockingPool, cache_, num_bytes),
      callback);
}

void FileSystem::CalculateCacheSize(const CacheSizeCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&CalculateCacheSizeOnBlockingPool, cache_), callback);
}

void FileSystem::CalculateEvictableCacheSize(
    const CacheSizeCallback& callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(callback);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(), FROM_HERE,
      base::Bind(&CalculateEvictableCacheSizeOnBlockingPool, cache_), callback);
}
}  // namespace drive
