// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/fileapi/diversion_backend_delegate.h"

#include <unistd.h>

#include "base/metrics/histogram_functions.h"
#include "chrome/browser/ash/fileapi/copy_from_fd.h"
#include "chrome/browser/ash/fusebox/fusebox_errno.h"
#include "chrome/browser/ash/fusebox/fusebox_histograms.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/common/file_system/file_system_util.h"

namespace ash {

namespace {

constexpr auto kDiversionFileIdleTimeout = base::Seconds(5);

DiversionBackendDelegate::Policy ShouldDivert(
    const storage::FileSystemURL& url) {
  // For now (January 2024), we'll be conservative and only apply diversion to
  // "crdownload" files (from browser downloads) or "crswap" files (as
  // generated by File System Access code) that are freshly created. Later, we
  // could roll out diversion more widely.
  //
  // If we were to divert previously-existing files (not only diverting freshly
  // created files), as kDivertMingled (not kDivertIsolated), then we'd need to
  // initialize the Diversion File's contents (via a FileStreamWriter), just
  // after the StartDiverting call, before running the
  // EnsureFileExistsCallback. There would be the usual trade-offs here between
  // lazy and eager initialization of those file contents.
  const std::string& extension = url.virtual_path().FinalExtension();
  if ((extension == ".crdownload") || (extension == ".crswap")) {
    return DiversionBackendDelegate::Policy::kDivertIsolated;
  } else if (extension == ".cros_divert_mingled_test") {
    return DiversionBackendDelegate::Policy::kDivertMingled;
  }
  return DiversionBackendDelegate::Policy::kDoNotDivert;
}

// Duplicates a FileSystemOperationContext, returning something (a unique_ptr)
// with independent ownership.
std::unique_ptr<storage::FileSystemOperationContext>
DuplicateFileSystemOperationContext(
    const storage::FileSystemOperationContext& original) {
  return std::make_unique<storage::FileSystemOperationContext>(
      original.file_system_context(), original.task_runner());
}

storage::AsyncFileUtil::StatusCallback HistogramWrap(
    const char* histogram_name,
    storage::AsyncFileUtil::StatusCallback callback) {
  static constexpr auto func =
      [](const char* histogram_name,
         storage::AsyncFileUtil::StatusCallback wrappee,
         base::File::Error error) {
        base::UmaHistogramEnumeration(histogram_name,
                                      fusebox::GetHistogramEnumPosixErrorCode(
                                          fusebox::FileErrorToErrno(error)));

        if (wrappee) {
          std::move(wrappee).Run(error);
        }
      };

  return base::BindOnce(func, histogram_name, std::move(callback));
}

}  // namespace

DiversionBackendDelegate::DiversionBackendDelegate(
    std::unique_ptr<FileSystemBackendDelegate> wrappee)
    : wrappee_(std::move(wrappee)),
      diversion_file_manager_(base::MakeRefCounted<DiversionFileManager>()) {
  CHECK(wrappee_);
}

DiversionBackendDelegate::~DiversionBackendDelegate() = default;

storage::AsyncFileUtil* DiversionBackendDelegate::GetAsyncFileUtil(
    storage::FileSystemType type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  return this;
}

std::unique_ptr<storage::FileStreamReader>
DiversionBackendDelegate::CreateFileStreamReader(
    const storage::FileSystemURL& url,
    int64_t offset,
    int64_t max_bytes_to_read,
    const base::Time& expected_modification_time,
    storage::FileSystemContext* context) {
  // TODO: honor max_bytes_to_read. On the other hand,
  // storage::FileStreamReader::CreateForLocalFile also doesn't honor it.
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (std::unique_ptr<storage::FileStreamReader> fs_reader =
          diversion_file_manager_->CreateDivertedFileStreamReader(url,
                                                                  offset)) {
    return fs_reader;
  }
  return wrappee_->CreateFileStreamReader(url, offset, max_bytes_to_read,
                                          expected_modification_time, context);
}

std::unique_ptr<storage::FileStreamWriter>
DiversionBackendDelegate::CreateFileStreamWriter(
    const storage::FileSystemURL& url,
    int64_t offset,
    storage::FileSystemContext* context) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (std::unique_ptr<storage::FileStreamWriter> fs_writer =
          diversion_file_manager_->CreateDivertedFileStreamWriter(url,
                                                                  offset)) {
    return fs_writer;
  }
  return wrappee_->CreateFileStreamWriter(url, offset, context);
}

storage::WatcherManager* DiversionBackendDelegate::GetWatcherManager(
    storage::FileSystemType type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  return wrappee_->GetWatcherManager(type);
}

void DiversionBackendDelegate::CreateOrOpen(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    uint32_t file_flags,
    CreateOrOpenCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->CreateOrOpen(std::move(context), url, file_flags,
                        std::move(callback));
}

void DiversionBackendDelegate::EnsureFileExists(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    EnsureFileExistsCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());

  if (!url.is_valid()) {
    std::move(callback).Run(base::File::FILE_ERROR_INVALID_URL,
                            /*created=*/false);
    return;
  }
  const Policy policy = ShouldDivert(url);
  base::UmaHistogramBoolean(
      "FileBrowser.Diversion.EnsureFileExists.ShouldDivert",
      policy != Policy::kDoNotDivert);
  if (policy == Policy::kDoNotDivert) {
    af_util->EnsureFileExists(std::move(context), url, std::move(callback));
    return;
  } else if (diversion_file_manager_->IsDiverting(url)) {
    std::move(callback).Run(base::File::FILE_OK, /*created=*/false);
    return;
  } else if (policy == Policy::kDivertIsolated) {
    auto sd_result = diversion_file_manager_->StartDiverting(
        url, kDiversionFileIdleTimeout,
        base::BindOnce(&DiversionBackendDelegate::OnDiversionFinished,
                       weak_ptr_factory_.GetWeakPtr(),
                       OnDiversionFinishedCallSite::kEnsureFileExists,
                       std::move(context), url,
                       storage::AsyncFileUtil::StatusCallback()));
    bool created = sd_result == DiversionFileManager::StartDivertingResult::kOK;
    std::move(callback).Run(base::File::FILE_OK, created);
    return;
  }

  static constexpr auto on_get_file_info =
      [](base::WeakPtr<DiversionBackendDelegate> weak_ptr,
         scoped_refptr<DiversionFileManager> diversion_file_manager,
         std::unique_ptr<storage::FileSystemOperationContext>
             duplicated_context,
         const storage::FileSystemURL& url, EnsureFileExistsCallback callback,
         base::File::Error gfi_result, const base::File::Info& file_info) {
        DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
        bool created = false;
        if (gfi_result == base::File::FILE_OK) {
          std::move(callback).Run(file_info.is_directory
                                      ? base::File::FILE_ERROR_NOT_A_FILE
                                      : base::File::FILE_OK,
                                  created);
        } else if (gfi_result == base::File::FILE_ERROR_NOT_FOUND) {
          auto sd_result = diversion_file_manager->StartDiverting(
              url, kDiversionFileIdleTimeout,
              base::BindOnce(&DiversionBackendDelegate::OnDiversionFinished,
                             std::move(weak_ptr),
                             OnDiversionFinishedCallSite::kEnsureFileExists,
                             std::move(duplicated_context), url,
                             storage::AsyncFileUtil::StatusCallback()));
          created =
              sd_result == DiversionFileManager::StartDivertingResult::kOK;
          std::move(callback).Run(base::File::FILE_OK, created);
        } else {
          std::move(callback).Run(gfi_result, created);
        }
      };

  std::unique_ptr<storage::FileSystemOperationContext> fsoc0 =
      DuplicateFileSystemOperationContext(*context);
  std::unique_ptr<storage::FileSystemOperationContext> fsoc1 =
      std::move(context);

  af_util->GetFileInfo(
      std::move(fsoc0), url,
      {storage::FileSystemOperation::GetMetadataField::kIsDirectory},
      base::BindOnce(on_get_file_info, weak_ptr_factory_.GetWeakPtr(),
                     diversion_file_manager_, std::move(fsoc1), url,
                     std::move(callback)));
}

void DiversionBackendDelegate::CreateDirectory(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    bool exclusive,
    bool recursive,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->CreateDirectory(std::move(context), url, exclusive, recursive,
                           std::move(callback));
}

void DiversionBackendDelegate::GetFileInfo(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    GetMetadataFieldSet fields,
    GetFileInfoCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (diversion_file_manager_->IsDiverting(url)) {
    diversion_file_manager_->GetDivertedFileInfo(url, fields,
                                                 std::move(callback));
    return;
  } else if (ShouldDivert(url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND,
                            base::File::Info());
    return;
  }
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->GetFileInfo(std::move(context), url, fields, std::move(callback));
}

void DiversionBackendDelegate::ReadDirectory(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    ReadDirectoryCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->ReadDirectory(std::move(context), url, std::move(callback));
}

void DiversionBackendDelegate::Touch(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    const base::Time& last_access_time,
    const base::Time& last_modified_time,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (diversion_file_manager_->IsDiverting(url)) {
    // TODO: touch the O_TMPFILE file.
  } else if (ShouldDivert(url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
    return;
  }
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->Touch(std::move(context), url, last_access_time, last_modified_time,
                 std::move(callback));
}

void DiversionBackendDelegate::Truncate(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    int64_t length,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (diversion_file_manager_->IsDiverting(url)) {
    diversion_file_manager_->TruncateDivertedFile(url, length,
                                                  std::move(callback));
    return;
  } else if (ShouldDivert(url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
    return;
  }
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->Truncate(std::move(context), url, length, std::move(callback));
}

void DiversionBackendDelegate::CopyFileLocal(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& src_url,
    const storage::FileSystemURL& dest_url,
    CopyOrMoveOptionSet options,
    CopyFileProgressCallback progress_callback,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (!src_url.is_valid() || !dest_url.is_valid()) {
    std::move(callback).Run(base::File::FILE_ERROR_INVALID_URL);
    return;
  } else if (src_url == dest_url) {
    std::move(callback).Run(base::File::FILE_OK);
    return;
  }

  if (diversion_file_manager_->IsDiverting(dest_url)) {
    // Passing a null DiversionFileManager::Callback deletes the diversion file.
    diversion_file_manager_->FinishDiverting(dest_url,
                                             DiversionFileManager::Callback());
  }

  if (diversion_file_manager_->IsDiverting(src_url)) {
    diversion_file_manager_->FinishDiverting(
        src_url,
        base::BindOnce(&DiversionBackendDelegate::OnDiversionFinished,
                       weak_ptr_factory_.GetWeakPtr(),
                       OnDiversionFinishedCallSite::kCopyFileLocal,
                       std::move(context), dest_url, std::move(callback)));
    return;
  } else if (ShouldDivert(src_url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
    return;
  }

  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(dest_url.type());
  af_util->CopyFileLocal(std::move(context), src_url, dest_url,
                         std::move(options), std::move(progress_callback),
                         std::move(callback));
}

void DiversionBackendDelegate::MoveFileLocal(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& src_url,
    const storage::FileSystemURL& dest_url,
    CopyOrMoveOptionSet options,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (!src_url.is_valid() || !dest_url.is_valid()) {
    std::move(callback).Run(base::File::FILE_ERROR_INVALID_URL);
    return;
  } else if (src_url == dest_url) {
    std::move(callback).Run(base::File::FILE_OK);
    return;
  }

  if (diversion_file_manager_->IsDiverting(src_url)) {
    diversion_file_manager_->FinishDiverting(
        src_url,
        base::BindOnce(&DiversionBackendDelegate::OnDiversionFinished,
                       weak_ptr_factory_.GetWeakPtr(),
                       OnDiversionFinishedCallSite::kMoveFileLocal,
                       std::move(context), dest_url, std::move(callback)));
    return;
  } else if (ShouldDivert(src_url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
    return;
  } else if (diversion_file_manager_->IsDiverting(dest_url)) {
    // Passing a null DiversionFileManager::Callback deletes the diversion file.
    diversion_file_manager_->FinishDiverting(dest_url,
                                             DiversionFileManager::Callback());
  }

  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(dest_url.type());
  af_util->MoveFileLocal(std::move(context), src_url, dest_url,
                         std::move(options), std::move(callback));
}

void DiversionBackendDelegate::CopyInForeignFile(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const base::FilePath& src_file_path,
    const storage::FileSystemURL& dest_url,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(dest_url.type());
  af_util->CopyInForeignFile(std::move(context), src_file_path, dest_url,
                             std::move(callback));
}

void DiversionBackendDelegate::DeleteFile(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (diversion_file_manager_->IsDiverting(url)) {
    // Passing a null DiversionFileManager::Callback deletes the diversion file.
    diversion_file_manager_->FinishDiverting(url,
                                             DiversionFileManager::Callback());
    if (callback) {
      callback = base::BindOnce(
          [](StatusCallback inner_callback, base::File::Error result) {
            if (result == base::File::FILE_ERROR_NOT_FOUND) {
              result = base::File::FILE_OK;
            }
            std::move(inner_callback).Run(result);
          },
          std::move(callback));
    }
  } else if (ShouldDivert(url) == Policy::kDivertIsolated) {
    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
    return;
  }
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->DeleteFile(std::move(context), url, std::move(callback));
}

void DiversionBackendDelegate::DeleteDirectory(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->DeleteDirectory(std::move(context), url, std::move(callback));
}

void DiversionBackendDelegate::DeleteRecursively(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  // TODO: this could be tricky if a diverted-file is a descendent of the "url
  // to be deleted recursively".
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->DeleteRecursively(std::move(context), url, std::move(callback));
}

void DiversionBackendDelegate::CreateSnapshotFile(
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& url,
    CreateSnapshotFileCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  // TODO: do we need to do anything here??
  storage::AsyncFileUtil* af_util = wrappee_->GetAsyncFileUtil(url.type());
  af_util->CreateSnapshotFile(std::move(context), url, std::move(callback));
}

void DiversionBackendDelegate::OverrideTmpfileDirForTesting(
    const base::FilePath& tmpfile_dir) {
  diversion_file_manager_->OverrideTmpfileDirForTesting(  // IN-TEST
      tmpfile_dir);
}

// static
DiversionBackendDelegate::Policy
DiversionBackendDelegate::ShouldDivertForTesting(
    const storage::FileSystemURL& url) {
  return ShouldDivert(url);
}

// static
base::TimeDelta DiversionBackendDelegate::IdleTimeoutForTesting() {
  return kDiversionFileIdleTimeout;
}

// static
void DiversionBackendDelegate::OnDiversionFinished(
    base::WeakPtr<DiversionBackendDelegate> weak_ptr,
    OnDiversionFinishedCallSite call_site,
    std::unique_ptr<storage::FileSystemOperationContext> context,
    const storage::FileSystemURL& dest_url,
    storage::AsyncFileUtil::StatusCallback callback,
    DiversionFileManager::StoppedReason stopped_reason,
    const storage::FileSystemURL& src_url,
    base::ScopedFD scoped_fd,
    int64_t file_size,
    base::File::Error error) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK(dest_url.is_valid());
  CHECK(src_url.is_valid());

  switch (stopped_reason) {
    case DiversionFileManager::StoppedReason::kExplicitFinish:
      base::UmaHistogramEnumeration(
          "FileBrowser.Diversion.Commit.ExplicitFinish.PartOne",
          fusebox::GetHistogramEnumPosixErrorCode(
              fusebox::FileErrorToErrno(error)));
      callback =
          HistogramWrap("FileBrowser.Diversion.Commit.ExplicitFinish.PartTwo",
                        std::move(callback));
      break;
    case DiversionFileManager::StoppedReason::kImplicitIdle:
      base::UmaHistogramEnumeration(
          "FileBrowser.Diversion.Commit.ImplicitIdle.PartOne",
          fusebox::GetHistogramEnumPosixErrorCode(
              fusebox::FileErrorToErrno(error)));
      callback =
          HistogramWrap("FileBrowser.Diversion.Commit.ImplicitIdle.PartTwo",
                        std::move(callback));
      break;
  }

  if (error != base::File::FILE_OK) {
    if (callback) {
      std::move(callback).Run(error);
    }
    return;
  } else if (!weak_ptr || !context || !scoped_fd.is_valid()) {
    if (callback) {
      std::move(callback).Run(base::File::FILE_ERROR_FAILED);
    }
    return;
  }

  // TODO(b/289322939): when wrapping a FileSystemProvider backend, can it
  // accept a Blob instead of using CopyFromFileDescriptor? The latter might
  // need the FileSystemProvider JS implementation to buffer the entire file's
  // contents in memory at once, which will obviously fail if those contents
  // are larger than the amount of available RAM.

  static constexpr auto ignore_file_error_not_found =
      [](storage::AsyncFileUtil::StatusCallback callback,
         base::File::Error file_error) {
        if (file_error == base::File::FILE_ERROR_NOT_FOUND) {
          file_error = base::File::FILE_OK;
        }
        if (callback) {
          std::move(callback).Run(file_error);
        }
      };

  static constexpr auto on_copy_complete =
      [](base::WeakPtr<DiversionBackendDelegate> weak_ptr,
         OnDiversionFinishedCallSite call_site,
         std::unique_ptr<storage::FileSystemOperationContext> context,
         const storage::FileSystemURL& src_url,
         const storage::FileSystemURL& dest_url,
         storage::AsyncFileUtil::StatusCallback callback,
         DiversionFileManager::StoppedReason stopped_reason, int64_t file_size,
         base::ScopedFD scoped_fd,
         std::unique_ptr<storage::FileStreamWriter> fs_writer,
         net::Error net_error) {
        DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

        if (src_url == dest_url) {
          if (callback) {
            std::move(callback).Run(storage::NetErrorToFileError(net_error));
          }
          return;
        }
        CHECK_NE(call_site, OnDiversionFinishedCallSite::kEnsureFileExists);

        if (callback && (net_error != net::OK)) {
          base::File::Error first_error =
              storage::NetErrorToFileError(net_error);
          callback = base::BindOnce(
              [](storage::AsyncFileUtil::StatusCallback inner_callback,
                 base::File::Error first_error_is_passed_on,
                 base::File::Error second_error_is_ignored) {
                std::move(inner_callback).Run(first_error_is_passed_on);
              },
              std::move(callback), first_error);
        }

        if (!weak_ptr) {
          if (callback) {
            std::move(callback).Run(base::File::FILE_ERROR_FAILED);
          }
          return;
        }

        switch (call_site) {
          case OnDiversionFinishedCallSite::kEnsureFileExists:
            NOTREACHED_NORETURN();

          case OnDiversionFinishedCallSite::kCopyFileLocal: {
            if (!scoped_fd.is_valid()) {
              std::move(callback).Run(base::File::FILE_ERROR_FAILED);
              return;
            }
            // Copy from that scoped_fd again, but this time to src_url instead
            // of to dest_url.
            lseek(scoped_fd.get(), 0, SEEK_SET);
            weak_ptr->OnDiversionFinished(
                weak_ptr, call_site, std::move(context), src_url,
                std::move(callback), stopped_reason, src_url,
                std::move(scoped_fd), file_size, base::File::FILE_OK);
            break;
          }

          case OnDiversionFinishedCallSite::kMoveFileLocal:
            if (ShouldDivert(src_url) == Policy::kDivertIsolated) {
              std::move(callback).Run(base::File::FILE_OK);
            } else {
              weak_ptr->wrappee_->GetAsyncFileUtil(src_url.type())
                  ->DeleteFile(std::move(context), src_url,
                               base::BindOnce(ignore_file_error_not_found,
                                              std::move(callback)));
            }
            break;
        }
      };

  static constexpr auto on_truncated =
      [](base::WeakPtr<DiversionBackendDelegate> weak_ptr,
         OnDiversionFinishedCallSite call_site,
         std::unique_ptr<storage::FileSystemOperationContext> context,
         base::ScopedFD scoped_fd, const storage::FileSystemURL& src_url,
         const storage::FileSystemURL& dest_url,
         storage::AsyncFileUtil::StatusCallback callback,
         DiversionFileManager::StoppedReason stopped_reason, int64_t file_size,
         base::File::Error result) {
        if (result != base::File::FILE_OK) {
          if (callback) {
            std::move(callback).Run(result);
          }
          return;
        } else if (!weak_ptr) {
          if (callback) {
            std::move(callback).Run(base::File::FILE_ERROR_FAILED);
          }
          return;
        }

        // TODO: for now, we are assuming that "write to foo.dat" is atomic:
        // other clients reading "foo.dat" will either see the complete old
        // version (if it existed) or the complete new version but not a
        // partial prefix of the new version. Specifically for ODFS+FSP, file
        // upload is indeed atomic.
        //
        // More generally, we may have to take multiple steps (the Google Drive
        // team call this a "File Dance"), first writing to a temporary sibling
        // file and then moving the sibling over the ultimate destination. But
        // this is obviously more complicated and has more failure states.
        //
        // Ideally, the wrappee FileSystemBackendDelegate or AsyncFileUtil
        // would be able to say whether it is capable of atomic upload (see
        // also b/289322939). Absent that, it's simplest to assume that it can.
        std::unique_ptr<storage::FileStreamWriter> fs_writer =
            weak_ptr->wrappee_->CreateFileStreamWriter(
                dest_url, 0, context->file_system_context());

        CopyFromFileDescriptor(
            std::move(scoped_fd), std::move(fs_writer),
            dest_url.mount_option().flush_policy(),
            base::BindOnce(on_copy_complete, std::move(weak_ptr), call_site,
                           std::move(context), src_url, dest_url,
                           std::move(callback), stopped_reason, file_size));
      };

  static constexpr auto on_ensure_file_exists =
      [](base::WeakPtr<DiversionBackendDelegate> weak_ptr,
         OnDiversionFinishedCallSite call_site,
         std::unique_ptr<storage::FileSystemOperationContext> context,
         base::ScopedFD scoped_fd, const storage::FileSystemURL& src_url,
         const storage::FileSystemURL& dest_url,
         storage::AsyncFileUtil::StatusCallback callback,
         DiversionFileManager::StoppedReason stopped_reason, int64_t file_size,
         base::File::Error result, bool created) {
        if (result != base::File::FILE_OK) {
          if (callback) {
            std::move(callback).Run(result);
          }
          return;
        } else if (!weak_ptr) {
          if (callback) {
            std::move(callback).Run(base::File::FILE_ERROR_FAILED);
          }
          return;
        } else if (created) {
          on_truncated(std::move(weak_ptr), call_site, std::move(context),
                       std::move(scoped_fd), src_url, dest_url,
                       std::move(callback), stopped_reason, file_size,
                       base::File::FILE_OK);
          return;
        }

        std::unique_ptr<storage::FileSystemOperationContext> fsoc0 =
            DuplicateFileSystemOperationContext(*context);
        std::unique_ptr<storage::FileSystemOperationContext> fsoc1 =
            std::move(context);

        FileSystemBackendDelegate* wrappee = weak_ptr->wrappee_.get();
        wrappee->GetAsyncFileUtil(dest_url.type())
            ->Truncate(
                std::move(fsoc0), dest_url, 0,
                base::BindOnce(on_truncated, std::move(weak_ptr), call_site,
                               std::move(fsoc1), std::move(scoped_fd), src_url,
                               dest_url, std::move(callback), stopped_reason,
                               file_size));
      };

  static constexpr auto on_get_file_info =
      [](base::WeakPtr<DiversionBackendDelegate> weak_ptr,
         OnDiversionFinishedCallSite call_site,
         std::unique_ptr<storage::FileSystemOperationContext> context,
         base::ScopedFD scoped_fd, const storage::FileSystemURL& src_url,
         const storage::FileSystemURL& dest_url,
         storage::AsyncFileUtil::StatusCallback callback,
         DiversionFileManager::StoppedReason stopped_reason, int64_t file_size,
         base::File::Error result, const base::File::Info& file_info) {
        if (result == base::File::FILE_ERROR_NOT_FOUND) {
          // No-op. Every other if-else branch returns.
        } else if (result != base::File::FILE_OK) {
          if (callback) {
            std::move(callback).Run(result);
          }
          return;
        } else if (file_info.is_directory) {
          if (callback) {
            std::move(callback).Run(base::File::FILE_ERROR_NOT_A_FILE);
          }
          return;
        } else if (file_info.size != 0) {
          on_ensure_file_exists(std::move(weak_ptr), call_site,
                                std::move(context), std::move(scoped_fd),
                                src_url, dest_url, std::move(callback),
                                stopped_reason, file_size, base::File::FILE_OK,
                                /*created=*/false);
          return;
        } else {
          on_truncated(std::move(weak_ptr), call_site, std::move(context),
                       std::move(scoped_fd), src_url, dest_url,
                       std::move(callback), stopped_reason, file_size,
                       base::File::FILE_OK);
          return;
        }

        std::unique_ptr<storage::FileSystemOperationContext> fsoc0 =
            DuplicateFileSystemOperationContext(*context);
        std::unique_ptr<storage::FileSystemOperationContext> fsoc1 =
            std::move(context);

        FileSystemBackendDelegate* wrappee = weak_ptr->wrappee_.get();
        wrappee->GetAsyncFileUtil(dest_url.type())
            ->EnsureFileExists(
                std::move(fsoc0), dest_url,
                base::BindOnce(on_ensure_file_exists, std::move(weak_ptr),
                               call_site, std::move(fsoc1),
                               std::move(scoped_fd), src_url, dest_url,
                               std::move(callback), stopped_reason, file_size));
      };

  std::unique_ptr<storage::FileSystemOperationContext> fsoc0 =
      DuplicateFileSystemOperationContext(*context);
  std::unique_ptr<storage::FileSystemOperationContext> fsoc1 =
      std::move(context);

  FileSystemBackendDelegate* wrappee = weak_ptr->wrappee_.get();
  wrappee->GetAsyncFileUtil(dest_url.type())
      ->GetFileInfo(
          std::move(fsoc0), dest_url,
          {storage::FileSystemOperation::GetMetadataField::kSize,
           storage::FileSystemOperation::GetMetadataField::kIsDirectory},
          base::BindOnce(on_get_file_info, std::move(weak_ptr), call_site,
                         std::move(fsoc1), std::move(scoped_fd), src_url,
                         dest_url, std::move(callback), stopped_reason,
                         file_size));
}

}  // namespace ash
