// Copyright 2020 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 "content/browser/native_io/native_io_host.h"

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/task/post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "content/browser/native_io/native_io_file_host.h"
#include "content/browser/native_io/native_io_manager.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/common/native_io/native_io_utils.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/native_io/native_io.mojom.h"

using blink::mojom::NativeIOError;
using blink::mojom::NativeIOErrorPtr;
using blink::mojom::NativeIOErrorType;

namespace content {

namespace {

bool IsValidNativeIONameCharacter(char name_char) {
  return base::IsAsciiLower(name_char) || base::IsAsciiDigit(name_char) ||
         name_char == '_';
}

// Maximum allowed filename length, inclusive.
const int kMaximumFilenameLength = 100;

bool IsValidNativeIOName(const std::string& name) {
  if (name.empty())
    return false;

  if (name.length() > kMaximumFilenameLength)
    return false;

  return std::all_of(name.begin(), name.end(), &IsValidNativeIONameCharacter);
}

base::FilePath GetNativeIOFilePath(const base::FilePath& root_path,
                                   const std::string& name) {
  DCHECK(IsValidNativeIOName(name));
  DCHECK(!root_path.empty());

  // This simple implementation assumes that the name doesn't have any special
  // meaning to the host operating system.
  base::FilePath file_path = root_path.AppendASCII(name);
  DCHECK(root_path.IsParent(file_path));
  return file_path;
}

// Creates a task runner suitable for running file I/O tasks.
scoped_refptr<base::TaskRunner> CreateFileTaskRunner() {
  // We use a SequencedTaskRunner so that there is a global ordering to a
  // storage key's directory operations.
  return base::ThreadPool::CreateSequencedTaskRunner({
      // Needed for file I/O.
      base::MayBlock(),

      // Reasonable compromise, given that a few database operations are
      // blocking, while most operations are not. We should be able to do better
      // when we get scheduling APIs on the Web Platform.
      base::TaskPriority::USER_VISIBLE,

      // BLOCK_SHUTDOWN is definitely not appropriate. We might be able to move
      // to CONTINUE_ON_SHUTDOWN after very careful analysis.
      base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
  });
}

// Performs the file I/O work in OpenFile().
std::pair<base::File, int64_t> DoOpenFile(const base::FilePath& root_path,
                                          const std::string& name) {
  DCHECK(IsValidNativeIOName(name));
  DCHECK(!root_path.empty());

  // Lazily create the storage key's directory.
  base::File::Error error;
  if (!base::CreateDirectoryAndGetError(root_path, &error))
    return {base::File(), /*file_length=*/0};

  // SHARE_DELETE allows the browser to delete files even if a compromised
  // renderer refuses to close its file handles.
  int open_flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
                   base::File::FLAG_WRITE | base::File::FLAG_SHARE_DELETE;
  base::File file(GetNativeIOFilePath(root_path, name), open_flags);

  int64_t file_length = file.IsValid() ? file.GetLength() : 0;

  return {std::move(file), file_length};
}

// Performs the file I/O work in DeleteFile().
std::pair<blink::mojom::NativeIOErrorPtr, int64_t> DoDeleteFile(
    const base::FilePath& root_path,
    const std::string& name) {
  DCHECK(IsValidNativeIOName(name));
  DCHECK(!root_path.empty());

  // If the storage key's directory wasn't created yet, there's nothing to
  // delete.
  if (!base::PathExists(root_path))
    return {NativeIOError::New(NativeIOErrorType::kSuccess, ""),
            /*deleted_file_length=*/0};

  int64_t deleted_file_length;
  base::FilePath file_path = GetNativeIOFilePath(root_path, name);
  // If the file wasn't created yet, there's nothing to delete.
  if (!base::PathExists(file_path))
    return {NativeIOError::New(NativeIOErrorType::kSuccess, ""),
            /*deleted_file_length=*/0};
  if (!base::GetFileSize(file_path, &deleted_file_length))
    return {NativeIOManager::FileErrorToNativeIOError(
                base::File::GetLastFileError()),
            /*deleted_file_length=*/0};

  if (!base::DeleteFile(file_path))
    return {NativeIOManager::FileErrorToNativeIOError(
                base::File::GetLastFileError()),
            /*deleted_file_length=*/0};

  return {NativeIOError::New(NativeIOErrorType::kSuccess, ""),
          deleted_file_length};
}

using GetAllFileNamesResult =
    std::pair<base::File::Error, std::vector<std::string>>;

// Performs the file I/O work in GetAllFileNames().
GetAllFileNamesResult DoGetAllFileNames(const base::FilePath& root_path) {
  DCHECK(!root_path.empty());

  std::vector<std::string> result;

  // If the storage key's directory wasn't created yet, there's no file to
  // report.
  if (!base::PathExists(root_path))
    return {base::File::FILE_OK, std::move(result)};

  base::FileEnumerator file_enumerator(
      root_path, /*recursive=*/false, base::FileEnumerator::FILES,
      /*pattern=*/base::FilePath::StringType(),
      base::FileEnumerator::FolderSearchPolicy::ALL,
      base::FileEnumerator::ErrorPolicy::STOP_ENUMERATION);

  // TODO(pwnall): The result vector can grow to an unbounded size. Add a limit
  //               parameter with a reasonable upper bound.

  for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    // If the file name has a non-ASCII character, |file_name| will be the empty
    // string. This will correctly be flagged as corruption by the check below.
    std::string file_name = file_path.BaseName().MaybeAsASCII();

    // Chrome's NativeIO implementation only creates files that have valid
    // NativeIO names. Any other file names imply directory corruption.
    if (!IsValidNativeIOName(file_name)) {
      // TODO(pwnall): Figure out the corruption handling strategy. We could
      //               silently ignore the corrupted file, delete it, or stop
      //               and report an error.
      continue;
    }
    result.push_back(std::move(file_name));
  }

  // Don't return a partial list of files if an error occurred. The partial list
  // isn't meaningful, and may be useful information for a compromised renderer.
  //
  // TODO(pwnall): Reconsider this if we end up making NativeIO unusually
  //               friendly to corruption recovery.
  base::File::Error enumeration_error = file_enumerator.GetError();
  if (enumeration_error != base::File::FILE_OK)
    result.clear();

  return {enumeration_error, std::move(result)};
}

// Performs the file I/O work in RenameFile().
NativeIOErrorPtr DoRenameFile(const base::FilePath& root_path,
                              const std::string& old_name,
                              const std::string& new_name) {
  DCHECK(!root_path.empty());
  DCHECK(IsValidNativeIOName(old_name));
  DCHECK(IsValidNativeIOName(new_name));

  base::File::Error error = base::File::FILE_OK;
  // If the storage key's directory wasn't created yet, there's nothing to
  // rename. This error cannot be used to determine the existence of files
  // outside of the storage key's directory, as |old_name| is a valid NativeIO
  // name.
  if (!base::PathExists(root_path) ||
      !base::PathExists(GetNativeIOFilePath(root_path, old_name))) {
    return NativeIOError::New(NativeIOErrorType::kNotFound,
                              "Source file does not exist");
  }

  // Do not overwrite an existing file. This error cannot be used to determine
  // the existence of files outside of the storage key's directory, as
  // `new_name` is a valid NativeIO name.
  if (base::PathExists(GetNativeIOFilePath(root_path, new_name)))
    return NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                              "Target file exists");

  base::ReplaceFile(GetNativeIOFilePath(root_path, old_name),
                    GetNativeIOFilePath(root_path, new_name), &error);
  return NativeIOManager::FileErrorToNativeIOError(error);
}

// Performs the file I/O work in DeleteAllData().
base::File::Error DoDeleteAllData(const base::FilePath& storage_key_dir) {
  DCHECK(!storage_key_dir.empty());
  CHECK(!storage_key_dir.ReferencesParent())
      << "Removing a parent directory is disallowed.";
  bool delete_success = base::DeletePathRecursively(storage_key_dir);
  if (!delete_success) {
    return base::File::GetLastFileError();
  }
  return base::File::FILE_OK;
}

}  // namespace

NativeIOHost::NativeIOHost(const blink::StorageKey& storage_key,
                           base::FilePath root_path,
#if defined(OS_MAC)
                           bool allow_set_length_ipc,
#endif  // defined(OS_MAC)
                           NativeIOManager* manager)
    : storage_key_(storage_key),
      root_path_(std::move(root_path)),
#if defined(OS_MAC)
      allow_set_length_ipc_(allow_set_length_ipc),
#endif  // defined(OS_MAC)
      manager_(manager),
      file_task_runner_(CreateFileTaskRunner()) {
  DCHECK(manager != nullptr);

  // base::Unretained is safe here because this NativeIOHost owns `receivers_`.
  // So, the unretained NativeIOHost is guaranteed to outlive `receivers_` and
  // the closure that it uses.
  receivers_.set_disconnect_handler(base::BindRepeating(
      &NativeIOHost::OnReceiverDisconnect, base::Unretained(this)));
}

NativeIOHost::~NativeIOHost() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

void NativeIOHost::BindReceiver(
    mojo::PendingReceiver<blink::mojom::NativeIOHost> receiver) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  receivers_.Add(this, std::move(receiver));
}

void NativeIOHost::OpenFile(
    const std::string& name,
    mojo::PendingReceiver<blink::mojom::NativeIOFileHost> file_host_receiver,
    OpenFileCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  if (is_incognito_mode()) {
    std::move(callback).Run(
        base::File(), /*file_length=*/0,
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "StorageFoundation unavailable for this host"));
    return;
  }

  if (delete_all_data_in_progress()) {
    std::move(callback).Run(
        base::File(), /*file_length=*/0,
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "Data removal pending on storage key"));
    return;
  }

  if (!IsValidNativeIOName(name)) {
    mojo::ReportBadMessage("Invalid file name");
    std::move(callback).Run(
        base::File(), /*file_length=*/0,
        NativeIOError::New(NativeIOErrorType::kUnknown, "Invalid file name"));
    return;
  }

  if (open_file_hosts_.find(name) != open_file_hosts_.end()) {
    std::move(callback).Run(
        base::File(), /*file_length=*/0,
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "File is open"));
    return;
  }

  auto insert_result = io_pending_files_.insert(name);
  bool insert_success = insert_result.second;
  if (!insert_success) {
    std::move(callback).Run(
        base::File(), /*file_length=*/0,
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "Operation pending on file"));
    return;
  }

  file_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoOpenFile, root_path_, name),
      base::BindOnce(&NativeIOHost::DidOpenFile, weak_factory_.GetWeakPtr(),
                     name, std::move(file_host_receiver), std::move(callback)));
}

void NativeIOHost::DeleteFile(const std::string& name,
                              DeleteFileCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  if (is_incognito_mode()) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "StorageFoundation unavailable for this host"),
        /*granted_capacity_delta=*/0);
    return;
  }

  if (delete_all_data_in_progress()) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "Data removal pending on storage key"),
        /*granted_capacity_delta=*/0);
    return;
  }

  if (!IsValidNativeIOName(name)) {
    mojo::ReportBadMessage("Invalid file name");
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kUnknown, "Invalid file name"),
        /*granted_capacity_delta=*/0);
    return;
  }

  if (open_file_hosts_.find(name) != open_file_hosts_.end()) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "File is open"),
        /*granted_capacity_delta=*/0);
    return;
  }

  auto insert_result = io_pending_files_.insert(name);
  bool insert_success = insert_result.second;
  if (!insert_success) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "Operation pending on file"),
        /*granted_capacity_delta=*/0);
    return;
  }

  manager_->quota_manager_proxy()->NotifyStorageAccessed(
      storage_key(), blink::mojom::StorageType::kTemporary, base::Time::Now());

  // The deletion task runs on the file_task_runner and is skipped on shutdown,
  // as is ok for storage key data deletion.
  file_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoDeleteFile, root_path_, name),
      base::BindOnce(&NativeIOHost::DidDeleteFile, weak_factory_.GetWeakPtr(),
                     name, std::move(callback)));
}

void NativeIOHost::GetAllFileNames(GetAllFileNamesCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  if (is_incognito_mode()) {
    std::move(callback).Run(false, {});
    return;
  }

  if (delete_all_data_in_progress()) {
    std::move(callback).Run(false, {});
    return;
  }

  manager_->quota_manager_proxy()->NotifyStorageAccessed(
      storage_key(), blink::mojom::StorageType::kTemporary, base::Time::Now());

  file_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoGetAllFileNames, root_path_),
      base::BindOnce(
          [](blink::mojom::NativeIOHost::GetAllFileNamesCallback callback,
             GetAllFileNamesResult result) {
            std::move(callback).Run(result.first == base::File::FILE_OK,
                                    std::move(result.second));
          },
          std::move(callback)));
}

void NativeIOHost::RenameFile(const std::string& old_name,
                              const std::string& new_name,
                              RenameFileCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  if (is_incognito_mode()) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "StorageFoundation unavailable for this host"));
    return;
  }

  if (delete_all_data_in_progress()) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kInvalidState,
                           "Data removal pending on storage key"));
    return;
  }

  if (!IsValidNativeIOName(old_name) || !IsValidNativeIOName(new_name)) {
    mojo::ReportBadMessage("Invalid file name");
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kUnknown, "Invalid file name"));
    return;
  }

  if (open_file_hosts_.find(old_name) != open_file_hosts_.end() ||
      open_file_hosts_.find(new_name) != open_file_hosts_.end()) {
    std::move(callback).Run(NativeIOError::New(
        NativeIOErrorType::kNoModificationAllowed, "Source file is open"));
    return;
  }

  if (open_file_hosts_.find(old_name) != open_file_hosts_.end()) {
    std::move(callback).Run(NativeIOError::New(
        NativeIOErrorType::kNoModificationAllowed, "Target file is open"));
    return;
  }

  auto old_iterator_and_success = io_pending_files_.insert(old_name);
  if (!old_iterator_and_success.second) {
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "Operation pending on source file"));
    return;
  }
  auto new_iterator_and_success = io_pending_files_.insert(new_name);
  if (!new_iterator_and_success.second) {
    io_pending_files_.erase(old_iterator_and_success.first);
    std::move(callback).Run(
        NativeIOError::New(NativeIOErrorType::kNoModificationAllowed,
                           "Operation pending on target file"));
    return;
  }

  file_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoRenameFile, root_path_, old_name, new_name),
      base::BindOnce(&NativeIOHost::DidRenameFile, weak_factory_.GetWeakPtr(),
                     old_name, new_name, std::move(callback)));
}

void NativeIOHost::RequestCapacityChange(
    int64_t capacity_delta,
    RequestCapacityChangeCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  if (is_incognito_mode()) {
    std::move(callback).Run(0);
    return;
  }

  // TODO(rstz): Implement quota limits.
  constexpr int64_t kMaximumAllocation = int64_t{8} * 1024 * 1024 * 1024;
  if (capacity_delta > kMaximumAllocation) {
    std::move(callback).Run(0);
    return;
  }
  std::move(callback).Run(capacity_delta);
}

void NativeIOHost::OnFileClose(NativeIOFileHost* file_host,
                               base::PassKey<NativeIOFileHost>) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(open_file_hosts_.count(file_host->file_name()) > 0);
  DCHECK_EQ(open_file_hosts_[file_host->file_name()].get(), file_host);

  open_file_hosts_.erase(file_host->file_name());
}

void NativeIOHost::DeleteAllData(DeleteAllDataCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(callback);

  delete_all_data_callbacks_.push_back(std::move(callback));
  if (delete_all_data_callbacks_.size() > 1) {
    return;
  }

  // Clearing open file hosts informs the renderer that the file handles should
  // not be used any longer.
  open_file_hosts_.clear();

  file_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoDeleteAllData, root_path_),
      base::BindOnce(&NativeIOHost::DidDeleteAllData,
                     weak_factory_.GetWeakPtr()));
}

void NativeIOHost::OnReceiverDisconnect() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // May delete `this`.
  manager_->OnHostReceiverDisconnect(this, base::PassKey<NativeIOHost>());
}

void NativeIOHost::DidOpenFile(
    const std::string& name,
    mojo::PendingReceiver<blink::mojom::NativeIOFileHost> file_host_receiver,
    OpenFileCallback callback,
    std::pair<base::File, int64_t> result) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(io_pending_files_.count(name));
  DCHECK(!open_file_hosts_.count(name));

  base::File file = std::move(result.first);
  int64_t length = result.second;
  io_pending_files_.erase(name);

  base::File::Error open_error = file.error_details();

  if (!file.IsValid()) {
    // Make sure an error is reported whenever the file is not valid.
    open_error = open_error != base::File::FILE_OK
                     ? open_error
                     : base::File::FILE_ERROR_FAILED;
    std::move(callback).Run(
        std::move(file), length,
        NativeIOManager::FileErrorToNativeIOError(open_error));
    return;
  }

  // DoOpenFile may create a file if none exists, which justifies
  // NotifyStorageModified.
  manager_->quota_manager_proxy()->NotifyStorageModified(
      storage::QuotaClientType::kNativeIO, storage_key(),
      blink::mojom::StorageType::kTemporary, 0, base::Time::Now());

  open_file_hosts_.insert({
    name, std::make_unique<NativeIOFileHost>(this, name,
#if defined(OS_MAC)
                                             allow_set_length_ipc_,
#endif  // defined(OS_MAC)
                                             std::move(file_host_receiver))
  });

  std::move(callback).Run(
      std::move(file), length,
      NativeIOManager::FileErrorToNativeIOError(open_error));
  return;
}

void NativeIOHost::DidDeleteFile(
    const std::string& name,
    DeleteFileCallback callback,
    std::pair<blink::mojom::NativeIOErrorPtr, int64_t> delete_result) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(io_pending_files_.count(name));
  DCHECK(!open_file_hosts_.count(name));

  io_pending_files_.erase(name);

  manager_->quota_manager_proxy()->NotifyStorageModified(
      storage::QuotaClientType::kNativeIO, storage_key(),
      blink::mojom::StorageType::kTemporary, 0, base::Time::Now());

  std::move(callback).Run(std::move(delete_result.first), delete_result.second);
  return;
}

void NativeIOHost::DidRenameFile(const std::string& old_name,
                                 const std::string& new_name,
                                 RenameFileCallback callback,
                                 NativeIOErrorPtr rename_error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(io_pending_files_.count(old_name));
  DCHECK(!open_file_hosts_.count(old_name));
  DCHECK(io_pending_files_.count(new_name));
  DCHECK(!open_file_hosts_.count(new_name));

  io_pending_files_.erase(old_name);
  io_pending_files_.erase(new_name);

  manager_->quota_manager_proxy()->NotifyStorageModified(
      storage::QuotaClientType::kNativeIO, storage_key(),
      blink::mojom::StorageType::kTemporary, 0, base::Time::Now());

  std::move(callback).Run(std::move(rename_error));
  return;
}

void NativeIOHost::DidDeleteAllData(base::File::Error error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Moving callbacks to a local variable to avoid race conditions if the vector
  // is accessed during callback execution.
  std::vector<DeleteAllDataCallback> callbacks =
      std::move(delete_all_data_callbacks_);
  delete_all_data_callbacks_.clear();
  for (DeleteAllDataCallback& callback : callbacks) {
    std::move(callback).Run(error);
  }

  // May delete `this`.
  manager_->DidDeleteHostData(this, base::PassKey<NativeIOHost>());
}

}  // namespace content
