// 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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

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

#include <fcntl.h>
#include <unistd.h>

#include <algorithm>
#include <limits>
#include <optional>
#include <utility>

#include "base/containers/circular_deque.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/clamped_math.h"
#include "base/posix/eintr_wrapper.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/buildflag.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/common/file_system/file_system_util.h"

static_assert(BUILDFLAG(IS_CHROMEOS), "For ChromeOS only");

namespace ash {

namespace {

// In theory, we could get this at runtime via Profile::GetPath and
// ProfileManager::GetActiveUserProfile, but calling those needs to happen on
// the UI thread while the code in this C++ primarily happens on the IO thread.
// It's simpler, since we're on ChromeOS, to just hard-code the home dir.
constexpr char kChronosHomeDir[] = "/home/chronos/user/";

using GetFileInfoCallback =
    base::OnceCallback<void(base::File::Error result,
                            const base::File::Info& file_info)>;
using StatusCallback = base::OnceCallback<void(base::File::Error result)>;

// A temporary file (as a file descriptor) and its size in bytes, or the first
// error (if any) encountered in accessing it.
//
// The underlying file (in the kernel sense) is an O_TMPFILE file (and so does
// not need any further Chromium code for garbage collecting used files),
// created under kChronosHomeDir (not /tmp) so that it is disk-backed instead
// of memory-backed, as disk is more plentiful than RAM.
//
// O_TMPFILE and the hard-coded kChronosHomeDir may be Linux-only and
// ChromeOS-only concepts but this C++ file only builds when IS_CHROMEOS.
struct Tmpfile {
  base::ScopedFD scoped_fd;
  int64_t file_size = 0;
  net::Error net_error = net::OK;

  Tmpfile() = default;
  explicit Tmpfile(net::Error e) : net_error(e) {}
};

// An asynchronous operation involving a transform function that runs on a
// base::BlockingType::MAY_BLOCK thread - it can perform blocking I/O. A
// Tmpfile (which holds a base::ScopedFD, an ownership type) is passed to that
// thread and is returned to the original (content::BrowserThread::IO) thread
// via the Callback.
//
// The transform field may be a null OnceCallback, meaning the identity (no-op)
// transform. The Callback field must not be a null OnceCallback.
struct Op {
  // The int means whatever the Transform and Callback agree that it means. It
  // often means the number of bytes read or written, or it is ignored. The
  // Tmpfile itself already holds a net::Error.
  using Transform = base::OnceCallback<std::pair<Tmpfile, int>(Tmpfile)>;
  using Callback = base::OnceCallback<void(const Tmpfile&, int)>;

  Transform transform;
  Callback callback;
};

}  // namespace

// A DiversionFileManager is essentially a map from FileSystemURL to
// scoped_refptr<Entry>. An Entry serializes the Ops enqueued to it such that
// at most one Op is in-flight at a time. It also holds the Tmpfile (which owns
// the underlying file descriptor, via a ScopedFD) when that Tmpfile is not
// loaned out to any in-flight Op.
//
// An Entry also starts an idle_timeout timer (1) at construction and (2) after
// each time the last (so far) reader/writer Worker is destroyed. If no new
// Workers were created (and Finish was not called) between a timer starting
// and expiring, the Entry times out and its implicit_callback is run.
class DiversionFileManager::Entry
    : public base::RefCounted<DiversionFileManager::Entry> {
 public:
  Entry(const storage::FileSystemURL& url,
        scoped_refptr<DiversionFileManager> manager,
        base::TimeDelta idle_timeout,
        Callback implicit_callback);

  void OnWorkerConstructed();
  void OnWorkerDestroyed();

  void Enqueue(Op op);

  void Finish(Callback explicit_callback);

 private:
  friend class base::RefCounted<DiversionFileManager::Entry>;
  ~Entry();

  void Run(Op op);
  void OnRunComplete(Op::Callback callback, std::pair<Tmpfile, int> tmpfile);
  bool ShouldRunCallback();
  void RunCallback();
  bool ShouldPostIdleTimer();
  void PostIdleTimer();

  static void OnIdleTimer(
      scoped_refptr<Entry> refptr_this,
      uint64_t num_workers_constructed_as_at_post_idle_timer);

  const storage::FileSystemURL url_;
  scoped_refptr<DiversionFileManager> manager_;
  base::TimeDelta idle_timeout_;

  Tmpfile tmpfile_;
  uint64_t num_workers_constructed_ = 0;
  uint64_t num_workers_destroyed_ = 0;
  std::optional<StoppedReason> stopped_reason_ = std::nullopt;
  bool is_running_an_op_ = false;
  base::circular_deque<Op> pending_ops_;
  Callback implicit_callback_;
  Callback explicit_callback_;
};

DiversionFileManager::Entry::Entry(const storage::FileSystemURL& url,
                                   scoped_refptr<DiversionFileManager> manager,
                                   base::TimeDelta idle_timeout,
                                   Callback implicit_callback)
    : url_(url),
      manager_(manager),
      idle_timeout_(idle_timeout),
      implicit_callback_(std::move(implicit_callback)) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  // transform creates the O_TMPFILE file.
  static constexpr auto transform =
      [](std::string tmpfile_dir, Tmpfile tmpfile) -> std::pair<Tmpfile, int> {
    base::ScopedBlockingCall scoped_blocking_call(
        FROM_HERE, base::BlockingType::MAY_BLOCK);

    base::ScopedFD sfd(open(tmpfile_dir.c_str(),
                            O_CLOEXEC | O_EXCL | O_TMPFILE | O_RDWR, 0600));
    if (sfd.is_valid()) {
      tmpfile.scoped_fd = std::move(sfd);
    } else {
      tmpfile.net_error = net::ERR_FILE_NO_SPACE;
    }
    return std::make_pair(std::move(tmpfile), 0);
  };

  Run({base::BindOnce(transform, manager->TmpfileDirAsString()),
       Op::Callback()});
  PostIdleTimer();
}

DiversionFileManager::Entry::~Entry() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}

void DiversionFileManager::Entry::OnWorkerConstructed() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  num_workers_constructed_++;
}

void DiversionFileManager::Entry::OnWorkerDestroyed() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  num_workers_destroyed_++;
  if (ShouldRunCallback()) {
    RunCallback();
  }
  if (ShouldPostIdleTimer()) {
    PostIdleTimer();
  }
}

void DiversionFileManager::Entry::Enqueue(Op op) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (is_running_an_op_) {
    pending_ops_.push_back(std::move(op));
  } else {
    Run(std::move(op));
  }
}

void DiversionFileManager::Entry::Run(Op op) {
  CHECK(!is_running_an_op_);
  is_running_an_op_ = true;

  if (op.transform) {
    base::ThreadPool::PostTaskAndReplyWithResult(
        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
        base::BindOnce(std::move(op.transform), std::move(tmpfile_)),
        base::BindOnce(&Entry::OnRunComplete, scoped_refptr<Entry>(this),
                       std::move(op.callback)));
  } else {
    OnRunComplete(std::move(op.callback),
                  std::make_pair(std::move(tmpfile_), 0));
  }
}

void DiversionFileManager::Entry::OnRunComplete(
    Op::Callback op_callback,
    std::pair<Tmpfile, int> result) {
  CHECK(is_running_an_op_);
  is_running_an_op_ = false;

  tmpfile_ = std::move(result.first);

  if (op_callback) {
    std::move(op_callback).Run(tmpfile_, result.second);
  }

  if (!pending_ops_.empty()) {
    Op op = std::move(pending_ops_.front());
    pending_ops_.pop_front();
    Run(std::move(op));
  } else if (ShouldRunCallback()) {
    RunCallback();
  }
}

void DiversionFileManager::Entry::Finish(Callback explicit_callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  CHECK(!stopped_reason_.has_value());
  stopped_reason_ = StoppedReason::kExplicitFinish;
  explicit_callback_ = std::move(explicit_callback);
  if (ShouldRunCallback()) {
    RunCallback();
  }
}

bool DiversionFileManager::Entry::ShouldRunCallback() {
  return !is_running_an_op_ && pending_ops_.empty() &&
         stopped_reason_.has_value() &&
         (num_workers_constructed_ == num_workers_destroyed_);
}

// Precondition: ShouldRunCallback().
void DiversionFileManager::Entry::RunCallback() {
  Callback callback;
  switch (stopped_reason_.value()) {
    case StoppedReason::kExplicitFinish:
      callback = std::move(explicit_callback_);
      break;
    case StoppedReason::kImplicitIdle:
      callback = std::move(implicit_callback_);
      break;
  }
  if (callback) {
    std::move(callback).Run(stopped_reason_.value(), url_,
                            std::move(tmpfile_.scoped_fd), tmpfile_.file_size,
                            storage::NetErrorToFileError(tmpfile_.net_error));
  }
}

bool DiversionFileManager::Entry::ShouldPostIdleTimer() {
  return !stopped_reason_.has_value() &&
         (num_workers_constructed_ == num_workers_destroyed_);
}

// Precondition: ShouldPostIdleTimer().
void DiversionFileManager::Entry::PostIdleTimer() {
  content::GetIOThreadTaskRunner({})->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&DiversionFileManager::Entry::OnIdleTimer,
                     scoped_refptr<Entry>(this), num_workers_constructed_),
      idle_timeout_);
}

// static
void DiversionFileManager::Entry::OnIdleTimer(
    scoped_refptr<Entry> refptr_this,
    uint64_t num_workers_constructed_as_at_post_idle_timer) {
  if (num_workers_constructed_as_at_post_idle_timer !=
      refptr_this->num_workers_constructed_) {
    return;
  } else if (refptr_this->stopped_reason_.has_value()) {
    return;
  }
  refptr_this->stopped_reason_ = StoppedReason::kImplicitIdle;

  DiversionFileManager::Map& map = refptr_this->manager_->entries_;
  if (auto iter = map.find(refptr_this->url_); iter != map.end()) {
    CHECK_EQ(refptr_this, iter->second);
    map.erase(iter);
  }

  if (refptr_this->ShouldRunCallback()) {
    refptr_this->RunCallback();
  }
}

// ----

// A reader or writer for an Entry's temporary-file. Each worker has an
// independent file-offset.
class DiversionFileManager::Worker : public storage::FileStreamReader,
                                     public storage::FileStreamWriter {
 public:
  enum class Role {
    kReader,
    kWriter,
  };

  Worker(Role role, scoped_refptr<Entry> entry, int64_t offset);
  ~Worker() override;

  // storage::FileStreamReader overrides.
  int Read(net::IOBuffer* buf,
           int buf_len,
           net::CompletionOnceCallback callback) override;
  int64_t GetLength(net::Int64CompletionOnceCallback callback) override;

  // storage::FileStreamWriter overrides.
  int Write(net::IOBuffer* buf,
            int buf_len,
            net::CompletionOnceCallback callback) override;
  int Cancel(net::CompletionOnceCallback callback) override;
  int Flush(storage::FlushMode flush_mode,
            net::CompletionOnceCallback callback) override;

 private:
  void ReadOrWrite(net::IOBuffer* buf,
                   int buf_len,
                   net::CompletionOnceCallback callback);
  static void OnReadOrWrite(base::WeakPtr<Worker> weak_ptr,
                            net::CompletionOnceCallback callback,
                            const Tmpfile& tmpfile,
                            int byte_count);

  Role role_;
  scoped_refptr<Entry> entry_;
  int64_t offset_;

  base::WeakPtrFactory<Worker> weak_ptr_factory_{this};
};

DiversionFileManager::Worker::Worker(Role role,
                                     scoped_refptr<Entry> entry,
                                     int64_t offset)
    : role_(role), entry_(std::move(entry)), offset_(offset) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  entry_->OnWorkerConstructed();
}

DiversionFileManager::Worker::~Worker() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  entry_->OnWorkerDestroyed();
}

int DiversionFileManager::Worker::Read(net::IOBuffer* buf,
                                       int buf_len,
                                       net::CompletionOnceCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK_EQ(role_, Role::kReader);
  ReadOrWrite(buf, buf_len, std::move(callback));
  return net::ERR_IO_PENDING;
}

int64_t DiversionFileManager::Worker::GetLength(
    net::Int64CompletionOnceCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK_EQ(role_, Role::kReader);

  static constexpr auto reply = [](net::Int64CompletionOnceCallback callback,
                                   const Tmpfile& tmpfile, int ignored) {
    std::move(callback).Run((tmpfile.net_error < 0)
                                ? static_cast<int64_t>(tmpfile.net_error)
                                : tmpfile.file_size);
  };

  entry_->Enqueue(
      {Op::Transform(), base::BindOnce(reply, std::move(callback))});

  return net::ERR_IO_PENDING;
}

int DiversionFileManager::Worker::Write(net::IOBuffer* buf,
                                        int buf_len,
                                        net::CompletionOnceCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK_EQ(role_, Role::kWriter);
  ReadOrWrite(buf, buf_len, std::move(callback));
  return net::ERR_IO_PENDING;
}

int DiversionFileManager::Worker::Cancel(net::CompletionOnceCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK_EQ(role_, Role::kWriter);
  // Unimplemented.
  return net::OK;
}

int DiversionFileManager::Worker::Flush(storage::FlushMode flush_mode,
                                        net::CompletionOnceCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  CHECK_EQ(role_, Role::kWriter);
  // Flush is a no-op. An O_TMPFILE file isn't persistent anyway if the process
  // crashes. Within this process (and its open file descriptor), any
  // previously written bytes should already be readable.
  return net::OK;
}

void DiversionFileManager::Worker::ReadOrWrite(
    net::IOBuffer* buf,
    int buf_len,
    net::CompletionOnceCallback callback) {
  static constexpr auto transform =
      [](Role role, char* data_ptr, int data_len, int64_t offset,
         Tmpfile tmpfile) -> std::pair<Tmpfile, int> {
    if (tmpfile.net_error != net::OK) {
      return std::make_pair(std::move(tmpfile), 0);
    } else if (!tmpfile.scoped_fd.is_valid()) {
      return std::make_pair(Tmpfile(net::ERR_INVALID_HANDLE), 0);
    }

    base::ScopedBlockingCall scoped_blocking_call(
        FROM_HERE, base::BlockingType::MAY_BLOCK);

    const int64_t original_offset = offset;
    const int fd = tmpfile.scoped_fd.get();
    while (data_len > 0) {
      if (offset > std::numeric_limits<off_t>::max()) {
        return std::make_pair(Tmpfile(net::ERR_FILE_TOO_BIG), 0);
      }

      size_t arg2 = static_cast<size_t>(data_len);
      off_t arg3 = static_cast<off_t>(offset);
      ssize_t n = (role == Role::kReader)
                      ? HANDLE_EINTR(pread(fd, data_ptr, arg2, arg3))
                      : HANDLE_EINTR(pwrite(fd, data_ptr, arg2, arg3));

      if (n == 0) {
        break;
      } else if (n < 0) {
        return std::make_pair(Tmpfile((errno == ENOSPC) ? net::ERR_FILE_NO_SPACE
                                                        : net::ERR_FAILED),
                              0);
      }

      data_ptr += n;
      data_len -= static_cast<int>(n);
      offset = base::ClampAdd(offset, static_cast<int64_t>(n));
    }

    tmpfile.file_size = std::max(tmpfile.file_size, offset);
    return std::make_pair(std::move(tmpfile),
                          static_cast<int>(offset - original_offset));
  };

  entry_->Enqueue(
      {base::BindOnce(transform, role_, buf->data(), buf_len, offset_),
       base::BindOnce(&DiversionFileManager::Worker::OnReadOrWrite,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback))});
}

// static
void DiversionFileManager::Worker::OnReadOrWrite(
    base::WeakPtr<Worker> weak_ptr,
    net::CompletionOnceCallback callback,
    const Tmpfile& tmpfile,
    int byte_count) {
  Worker* weak_this = weak_ptr.get();
  if (weak_this && (byte_count > 0)) {
    weak_this->offset_ =
        base::ClampAdd(weak_this->offset_, static_cast<int64_t>(byte_count));
  }
  std::move(callback).Run((tmpfile.net_error < 0) ? tmpfile.net_error
                                                  : byte_count);
}

// ----

DiversionFileManager::DiversionFileManager() = default;

DiversionFileManager::~DiversionFileManager() = default;

bool DiversionFileManager::IsDiverting(const storage::FileSystemURL& url) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  return entries_.find(url) != entries_.end();
}

DiversionFileManager::StartDivertingResult DiversionFileManager::StartDiverting(
    const storage::FileSystemURL& url,
    base::TimeDelta idle_timeout,
    Callback implicit_callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  const auto [iter, success] = entries_.insert(
      std::make_pair(url, base::MakeRefCounted<Entry>(
                              url, scoped_refptr<DiversionFileManager>(this),
                              idle_timeout, std::move(implicit_callback))));

  return success
             ? DiversionFileManager::StartDivertingResult::kOK
             : DiversionFileManager::StartDivertingResult::kWasAlreadyDiverted;
}

DiversionFileManager::FinishDivertingResult
DiversionFileManager::FinishDiverting(const storage::FileSystemURL& url,
                                      Callback explicit_callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (auto iter = entries_.find(url); iter != entries_.end()) {
    scoped_refptr<Entry> entry = std::move(iter->second);
    entries_.erase(iter);
    entry->Finish(std::move(explicit_callback));
    return DiversionFileManager::FinishDivertingResult::kOK;
  }
  return DiversionFileManager::FinishDivertingResult::kWasNotDiverting;
}

std::unique_ptr<storage::FileStreamReader>
DiversionFileManager::CreateDivertedFileStreamReader(
    const storage::FileSystemURL& url,
    int64_t offset) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (auto iter = entries_.find(url); iter != entries_.end()) {
    return std::make_unique<Worker>(Worker::Role::kReader, iter->second,
                                    offset);
  }
  return nullptr;
}

std::unique_ptr<storage::FileStreamWriter>
DiversionFileManager::CreateDivertedFileStreamWriter(
    const storage::FileSystemURL& url,
    int64_t offset) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (auto iter = entries_.find(url); iter != entries_.end()) {
    return std::make_unique<Worker>(Worker::Role::kWriter, iter->second,
                                    offset);
  }
  return nullptr;
}

void DiversionFileManager::GetDivertedFileInfo(
    const storage::FileSystemURL& url,
    storage::FileSystemOperation::GetMetadataFieldSet fields,
    GetFileInfoCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  static constexpr auto reply = [](GetFileInfoCallback callback,
                                   const Tmpfile& tmpfile, int ignored) {
    base::File::Info info;
    if (tmpfile.net_error != net::OK) {
      std::move(callback).Run(storage::NetErrorToFileError(tmpfile.net_error),
                              info);
      return;
    }
    info.size = tmpfile.file_size;
    info.is_directory = false;
    info.is_symbolic_link = false;
    std::move(callback).Run(base::File::FILE_OK, info);
  };

  if (auto iter = entries_.find(url); iter != entries_.end()) {
    iter->second->Enqueue(
        {Op::Transform(), base::BindOnce(reply, std::move(callback))});
    return;
  }

  base::File::Info info;
  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION, info);
}

void DiversionFileManager::TruncateDivertedFile(
    const storage::FileSystemURL& url,
    int64_t length,
    StatusCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  static constexpr auto transform =
      [](int64_t length, Tmpfile tmpfile) -> std::pair<Tmpfile, int> {
    if (tmpfile.net_error != net::OK) {
      return std::make_pair(std::move(tmpfile), 0);
    } else if (!tmpfile.scoped_fd.is_valid()) {
      return std::make_pair(Tmpfile(net::ERR_INVALID_HANDLE), 0);
    } else if ((length < 0) || (static_cast<uint64_t>(length) >
                                std::numeric_limits<off_t>::max())) {
      return std::make_pair(Tmpfile(net::ERR_INVALID_ARGUMENT), 0);
    }

    base::ScopedBlockingCall scoped_blocking_call(
        FROM_HERE, base::BlockingType::MAY_BLOCK);

    if (HANDLE_EINTR(ftruncate(tmpfile.scoped_fd.get(),
                               static_cast<off_t>(length))) < 0) {
      tmpfile.net_error = net::ERR_FAILED;
    }

    return std::make_pair(std::move(tmpfile), 0);
  };

  static constexpr auto reply = [](StatusCallback callback,
                                   const Tmpfile& tmpfile, int ignored) {
    std::move(callback).Run(storage::NetErrorToFileError(tmpfile.net_error));
  };

  if (auto iter = entries_.find(url); iter != entries_.end()) {
    iter->second->Enqueue({base::BindOnce(transform, length),
                           base::BindOnce(reply, std::move(callback))});
    return;
  }

  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
}

void DiversionFileManager::OverrideTmpfileDirForTesting(
    const base::FilePath& tmpfile_dir) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  tmpfile_dir_ = tmpfile_dir;
}

std::string DiversionFileManager::TmpfileDirAsString() const {
  return tmpfile_dir_.empty() ? std::string(kChronosHomeDir)
                              : tmpfile_dir_.AsUTF8Unsafe();
}

}  // namespace ash
