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

#include <utility>

#include "base/barrier_closure.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "build/build_config.h"
#include "net/base/cache_type.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/backend_cleanup_tracker.h"
#include "net/disk_cache/blockfile/backend_impl.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/memory/mem_backend_impl.h"
#include "net/disk_cache/simple/simple_backend_impl.h"
#include "net/disk_cache/simple/simple_file_enumerator.h"
#include "net/disk_cache/simple/simple_util.h"

namespace {

using FileEnumerator = disk_cache::BackendFileOperations::FileEnumerator;

// Builds an instance of the backend depending on platform, type, experiments
// etc. Takes care of the retry state. This object will self-destroy when
// finished.
class CacheCreator {
 public:
  CacheCreator(const base::FilePath& path,
               disk_cache::ResetHandling reset_handling,
               int64_t max_bytes,
               net::CacheType type,
               net::BackendType backend_type,
               scoped_refptr<disk_cache::BackendFileOperationsFactory>
                   file_operations_factory,
#if BUILDFLAG(IS_ANDROID)
               base::android::ApplicationStatusListener* app_status_listener,
#endif
               net::NetLog* net_log,
               base::OnceClosure post_cleanup_callback,
               disk_cache::BackendResultCallback callback);

  CacheCreator(const CacheCreator&) = delete;
  CacheCreator& operator=(const CacheCreator&) = delete;

  // Wait for any previous backends for given path to finish clean up and then
  // attempt to create a new one. This will never succeed synchronously, though
  // it may fail synchronously.
  net::Error TryCreateCleanupTrackerAndRun();

  // Creates the backend, the cleanup context for it having been already
  // established... or purposefully left as null. This will never succeed
  // synchronously, though it may fail synchronously.
  net::Error Run();

 private:
  ~CacheCreator();

  void DoCallback(int result);

  void OnIOComplete(int result);
  void OnCacheCleanupComplete(int original_error, bool cleanup_result);

  const base::FilePath path_;
  disk_cache::ResetHandling reset_handling_;
  bool retry_ = false;
  int64_t max_bytes_;
  net::CacheType type_;
  net::BackendType backend_type_;
  scoped_refptr<disk_cache::BackendFileOperationsFactory>
      file_operations_factory_;
  std::unique_ptr<disk_cache::BackendFileOperations> file_operations_;
#if BUILDFLAG(IS_ANDROID)
  raw_ptr<base::android::ApplicationStatusListener> app_status_listener_;
#endif
  base::OnceClosure post_cleanup_callback_;
  disk_cache::BackendResultCallback callback_;
  std::unique_ptr<disk_cache::Backend> created_cache_;
  raw_ptr<net::NetLog> net_log_;
  scoped_refptr<disk_cache::BackendCleanupTracker> cleanup_tracker_;
};

CacheCreator::CacheCreator(
    const base::FilePath& path,
    disk_cache::ResetHandling reset_handling,
    int64_t max_bytes,
    net::CacheType type,
    net::BackendType backend_type,
    scoped_refptr<disk_cache::BackendFileOperationsFactory> file_operations,
#if BUILDFLAG(IS_ANDROID)
    base::android::ApplicationStatusListener* app_status_listener,
#endif
    net::NetLog* net_log,
    base::OnceClosure post_cleanup_callback,
    disk_cache::BackendResultCallback callback)
    : path_(path),
      reset_handling_(reset_handling),
      max_bytes_(max_bytes),
      type_(type),
      backend_type_(backend_type),
      file_operations_factory_(std::move(file_operations)),
#if BUILDFLAG(IS_ANDROID)
      app_status_listener_(app_status_listener),
#endif
      post_cleanup_callback_(std::move(post_cleanup_callback)),
      callback_(std::move(callback)),
      net_log_(net_log) {
}

CacheCreator::~CacheCreator() = default;

net::Error CacheCreator::Run() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
  static const bool kSimpleBackendIsDefault = true;
#else
  static const bool kSimpleBackendIsDefault = false;
#endif
  if (!retry_ && reset_handling_ == disk_cache::ResetHandling::kReset) {
    // Pretend that we failed to create a cache, so that we can handle `kReset`
    // and `kResetOnError` in a unified way, in CacheCreator::OnIOComplete.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(&CacheCreator::OnIOComplete,
                                  base::Unretained(this), net::ERR_FAILED));
    return net::ERR_IO_PENDING;
  }
  if (backend_type_ == net::CACHE_BACKEND_SIMPLE ||
      (backend_type_ == net::CACHE_BACKEND_DEFAULT &&
       kSimpleBackendIsDefault)) {
    auto cache = std::make_unique<disk_cache::SimpleBackendImpl>(
        file_operations_factory_, path_, cleanup_tracker_.get(),
        /* file_tracker = */ nullptr, max_bytes_, type_, net_log_);
    disk_cache::SimpleBackendImpl* simple_cache = cache.get();
    created_cache_ = std::move(cache);
#if BUILDFLAG(IS_ANDROID)
    if (app_status_listener_)
      simple_cache->set_app_status_listener(app_status_listener_);
#endif
    simple_cache->Init(
        base::BindOnce(&CacheCreator::OnIOComplete, base::Unretained(this)));
    return net::ERR_IO_PENDING;
  }

// Avoid references to blockfile functions on Android to reduce binary size.
#if BUILDFLAG(IS_ANDROID)
  return net::ERR_FAILED;
#else
  auto cache = std::make_unique<disk_cache::BackendImpl>(
      path_, cleanup_tracker_.get(),
      /*cache_thread = */ nullptr, type_, net_log_);
  disk_cache::BackendImpl* new_cache = cache.get();
  created_cache_ = std::move(cache);
  new_cache->SetMaxSize(max_bytes_);
  new_cache->Init(
      base::BindOnce(&CacheCreator::OnIOComplete, base::Unretained(this)));
  return net::ERR_IO_PENDING;
#endif
}

net::Error CacheCreator::TryCreateCleanupTrackerAndRun() {
  // Before creating a cache Backend, a BackendCleanupTracker object is needed
  // so there is a place to keep track of outstanding I/O even after the backend
  // object itself is destroyed, so that further use of the directory
  // doesn't race with those outstanding disk I/O ops.

  // This method's purpose it to grab exlusive ownership of a fresh
  // BackendCleanupTracker for the cache path, and then move on to Run(),
  // which will take care of creating the actual cache backend. It's possible
  // that something else is currently making use of the directory, in which
  // case BackendCleanupTracker::TryCreate will fail, but will just have
  // TryCreateCleanupTrackerAndRun run again at an opportune time to make
  // another attempt.

  // The resulting BackendCleanupTracker is stored into a scoped_refptr member
  // so that it's kept alive while |this| CacheCreator exists , so that in the
  // case Run() needs to retry Backend creation the same BackendCleanupTracker
  // is used for both attempts, and |post_cleanup_callback_| gets called after
  // the second try, not the first one.
  cleanup_tracker_ = disk_cache::BackendCleanupTracker::TryCreate(
      path_, base::BindOnce(base::IgnoreResult(
                                &CacheCreator::TryCreateCleanupTrackerAndRun),
                            base::Unretained(this)));
  if (!cleanup_tracker_)
    return net::ERR_IO_PENDING;
  if (!post_cleanup_callback_.is_null())
    cleanup_tracker_->AddPostCleanupCallback(std::move(post_cleanup_callback_));
  return Run();
}

void CacheCreator::DoCallback(int net_error) {
  DCHECK_NE(net::ERR_IO_PENDING, net_error);
  disk_cache::BackendResult result;
  if (net_error == net::OK) {
    result = disk_cache::BackendResult::Make(std::move(created_cache_));
  } else {
    LOG(ERROR) << "Unable to create cache";
    result = disk_cache::BackendResult::MakeError(
        static_cast<net::Error>(net_error));
    created_cache_.reset();
  }
  std::move(callback_).Run(std::move(result));
  delete this;
}

// If the initialization of the cache fails, and |reset_handling| isn't set to
// kNeverReset, we will discard the whole cache and create a new one.
void CacheCreator::OnIOComplete(int result) {
  DCHECK_NE(result, net::ERR_IO_PENDING);
  if (result == net::OK ||
      reset_handling_ == disk_cache::ResetHandling::kNeverReset || retry_) {
    return DoCallback(result);
  }

  // We are supposed to try again, so delete the object and all files and do so.
  retry_ = true;
  created_cache_.reset();

  if (!file_operations_) {
    if (file_operations_factory_) {
      file_operations_ = file_operations_factory_->Create(
          base::SequencedTaskRunner::GetCurrentDefault());
    } else {
      file_operations_ = std::make_unique<disk_cache::TrivialFileOperations>();
    }
  }
  file_operations_->CleanupDirectory(
      path_, base::BindOnce(&CacheCreator::OnCacheCleanupComplete,
                            base::Unretained(this), result));
}

void CacheCreator::OnCacheCleanupComplete(int original_result,
                                          bool cleanup_result) {
  if (!cleanup_result) {
    // Cleaning up the cache directory fails, so this operation should be
    // considered failed.
    DCHECK_NE(original_result, net::OK);
    DCHECK_NE(original_result, net::ERR_IO_PENDING);
    DoCallback(original_result);
    return;
  }

  // The worker thread may be deleting files, but the original folder
  // is not there anymore... let's create a new set of files.
  int rv = Run();
  DCHECK_EQ(net::ERR_IO_PENDING, rv);
}

class TrivialFileEnumerator final : public FileEnumerator {
 public:
  using FileEnumerationEntry =
      disk_cache::BackendFileOperations::FileEnumerationEntry;

  explicit TrivialFileEnumerator(const base::FilePath& path)
      : enumerator_(path) {}
  ~TrivialFileEnumerator() override = default;

  absl::optional<FileEnumerationEntry> Next() override {
    return enumerator_.Next();
  }
  bool HasError() const override { return enumerator_.HasError(); }

 private:
  disk_cache::SimpleFileEnumerator enumerator_;
};

class UnboundTrivialFileOperations
    : public disk_cache::UnboundBackendFileOperations {
 public:
  std::unique_ptr<disk_cache::BackendFileOperations> Bind(
      scoped_refptr<base::SequencedTaskRunner> task_runner) override {
    return std::make_unique<disk_cache::TrivialFileOperations>();
  }
};

}  // namespace

namespace disk_cache {

BackendResult::BackendResult() = default;
BackendResult::~BackendResult() = default;
BackendResult::BackendResult(BackendResult&&) = default;
BackendResult& BackendResult::operator=(BackendResult&&) = default;

// static
BackendResult BackendResult::MakeError(net::Error error_in) {
  DCHECK_NE(error_in, net::OK);
  BackendResult result;
  result.net_error = error_in;
  return result;
}

// static
BackendResult BackendResult::Make(std::unique_ptr<Backend> backend_in) {
  DCHECK(backend_in);
  BackendResult result;
  result.net_error = net::OK;
  result.backend = std::move(backend_in);
  return result;
}

BackendResult CreateCacheBackendImpl(
    net::CacheType type,
    net::BackendType backend_type,
    scoped_refptr<BackendFileOperationsFactory> file_operations,
    const base::FilePath& path,
    int64_t max_bytes,
    ResetHandling reset_handling,
#if BUILDFLAG(IS_ANDROID)
    base::android::ApplicationStatusListener* app_status_listener,
#endif
    net::NetLog* net_log,
    base::OnceClosure post_cleanup_callback,
    BackendResultCallback callback) {
  DCHECK(!callback.is_null());

  if (type == net::MEMORY_CACHE) {
    std::unique_ptr<MemBackendImpl> mem_backend_impl =
        disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log);
    if (mem_backend_impl) {
      mem_backend_impl->SetPostCleanupCallback(
          std::move(post_cleanup_callback));
      return BackendResult::Make(std::move(mem_backend_impl));
    } else {
      if (!post_cleanup_callback.is_null())
        base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
            FROM_HERE, std::move(post_cleanup_callback));
      return BackendResult::MakeError(net::ERR_FAILED);
    }
  }

  bool had_post_cleanup_callback = !post_cleanup_callback.is_null();
  CacheCreator* creator = new CacheCreator(
      path, reset_handling, max_bytes, type, backend_type,
      std::move(file_operations),
#if BUILDFLAG(IS_ANDROID)
      std::move(app_status_listener),
#endif
      net_log, std::move(post_cleanup_callback), std::move(callback));
  if (type == net::DISK_CACHE) {
    DCHECK(!had_post_cleanup_callback);
    return BackendResult::MakeError(creator->Run());
  }

  return BackendResult::MakeError(creator->TryCreateCleanupTrackerAndRun());
}

BackendResult CreateCacheBackend(
    net::CacheType type,
    net::BackendType backend_type,
    scoped_refptr<BackendFileOperationsFactory> file_operations,
    const base::FilePath& path,
    int64_t max_bytes,
    ResetHandling reset_handling,
    net::NetLog* net_log,
    BackendResultCallback callback) {
  return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
                                path, max_bytes, reset_handling,
#if BUILDFLAG(IS_ANDROID)
                                nullptr,
#endif
                                net_log, base::OnceClosure(),
                                std::move(callback));
}

#if BUILDFLAG(IS_ANDROID)
NET_EXPORT BackendResult CreateCacheBackend(
    net::CacheType type,
    net::BackendType backend_type,
    scoped_refptr<BackendFileOperationsFactory> file_operations,
    const base::FilePath& path,
    int64_t max_bytes,
    ResetHandling reset_handling,
    net::NetLog* net_log,
    BackendResultCallback callback,
    base::android::ApplicationStatusListener* app_status_listener) {
  return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
                                path, max_bytes, reset_handling,
                                std::move(app_status_listener), net_log,
                                base::OnceClosure(), std::move(callback));
}
#endif

BackendResult CreateCacheBackend(
    net::CacheType type,
    net::BackendType backend_type,
    scoped_refptr<BackendFileOperationsFactory> file_operations,
    const base::FilePath& path,
    int64_t max_bytes,
    ResetHandling reset_handling,
    net::NetLog* net_log,
    base::OnceClosure post_cleanup_callback,
    BackendResultCallback callback) {
  return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
                                path, max_bytes, reset_handling,
#if BUILDFLAG(IS_ANDROID)
                                nullptr,
#endif
                                net_log, std::move(post_cleanup_callback),
                                std::move(callback));
}

void FlushCacheThreadForTesting() {
  // For simple backend.
  base::ThreadPoolInstance::Get()->FlushForTesting();

  // Block backend.
  BackendImpl::FlushForTesting();
}

void FlushCacheThreadAsynchronouslyForTesting(base::OnceClosure callback) {
  auto repeating_callback = base::BarrierClosure(2, std::move(callback));

  // For simple backend.
  base::ThreadPoolInstance::Get()->FlushAsyncForTesting(  // IN-TEST
      base::BindPostTaskToCurrentDefault(repeating_callback));

  // Block backend.
  BackendImpl::FlushAsynchronouslyForTesting(repeating_callback);
}

int64_t Backend::CalculateSizeOfEntriesBetween(
    base::Time initial_time,
    base::Time end_time,
    Int64CompletionOnceCallback callback) {
  return net::ERR_NOT_IMPLEMENTED;
}

uint8_t Backend::GetEntryInMemoryData(const std::string& key) {
  return 0;
}

void Backend::SetEntryInMemoryData(const std::string& key, uint8_t data) {}

EntryResult::EntryResult() = default;
EntryResult::~EntryResult() = default;

EntryResult::EntryResult(EntryResult&& other) {
  net_error_ = other.net_error_;
  entry_ = std::move(other.entry_);
  opened_ = other.opened_;

  other.net_error_ = net::ERR_FAILED;
  other.opened_ = false;
}

EntryResult& EntryResult::operator=(EntryResult&& other) {
  net_error_ = other.net_error_;
  entry_ = std::move(other.entry_);
  opened_ = other.opened_;

  other.net_error_ = net::ERR_FAILED;
  other.opened_ = false;
  return *this;
}

// static
EntryResult EntryResult::MakeOpened(Entry* new_entry) {
  DCHECK(new_entry);

  EntryResult result;
  result.net_error_ = net::OK;
  result.entry_.reset(new_entry);
  result.opened_ = true;
  return result;
}

// static
EntryResult EntryResult::MakeCreated(Entry* new_entry) {
  DCHECK(new_entry);

  EntryResult result;
  result.net_error_ = net::OK;
  result.entry_.reset(new_entry);
  result.opened_ = false;
  return result;
}

// static
EntryResult EntryResult::MakeError(net::Error status) {
  DCHECK_NE(status, net::OK);

  EntryResult result;
  result.net_error_ = status;
  return result;
}

Entry* EntryResult::ReleaseEntry() {
  Entry* ret = entry_.release();
  net_error_ = net::ERR_FAILED;
  opened_ = false;
  return ret;
}

TrivialFileOperations::TrivialFileOperations() {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

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

bool TrivialFileOperations::CreateDirectory(const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  // This is needed for some unittests.
  if (path.empty()) {
    return false;
  }

  DCHECK(path.IsAbsolute());

  bool result = base::CreateDirectory(path);
  return result;
}

bool TrivialFileOperations::PathExists(const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  // This is needed for some unittests.
  if (path.empty()) {
    return false;
  }

  DCHECK(path.IsAbsolute());

  bool result = base::PathExists(path);
  return result;
}

bool TrivialFileOperations::DirectoryExists(const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  bool result = base::DirectoryExists(path);
  return result;
}

base::File TrivialFileOperations::OpenFile(const base::FilePath& path,
                                           uint32_t flags) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  base::File file(path, flags);
  return file;
}

bool TrivialFileOperations::DeleteFile(const base::FilePath& path,
                                       DeleteFileMode mode) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  bool result = false;
  switch (mode) {
    case DeleteFileMode::kDefault:
      result = base::DeleteFile(path);
      break;
    case DeleteFileMode::kEnsureImmediateAvailability:
      result = disk_cache::simple_util::SimpleCacheDeleteFile(path);
      break;
  }
  return result;
}

bool TrivialFileOperations::ReplaceFile(const base::FilePath& from_path,
                                        const base::FilePath& to_path,
                                        base::File::Error* error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(from_path.IsAbsolute());
  DCHECK(to_path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  return base::ReplaceFile(from_path, to_path, error);
}

absl::optional<base::File::Info> TrivialFileOperations::GetFileInfo(
    const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  base::File::Info file_info;
  if (!base::GetFileInfo(path, &file_info)) {
    return absl::nullopt;
  }
  return file_info;
}

std::unique_ptr<FileEnumerator> TrivialFileOperations::EnumerateFiles(
    const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif
  return std::make_unique<TrivialFileEnumerator>(path);
}

void TrivialFileOperations::CleanupDirectory(
    const base::FilePath& path,
    base::OnceCallback<void(bool)> callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // This is needed for some unittests.
  if (path.empty()) {
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), false));
    return;
  }

  DCHECK(path.IsAbsolute());
#if DCHECK_IS_ON()
  DCHECK(bound_);
#endif

  disk_cache::CleanupDirectory(path, std::move(callback));
}

std::unique_ptr<UnboundBackendFileOperations> TrivialFileOperations::Unbind() {
#if DCHECK_IS_ON()
  DCHECK(bound_);
  bound_ = false;
#endif
  return std::make_unique<UnboundTrivialFileOperations>();
}

TrivialFileOperationsFactory::TrivialFileOperationsFactory() = default;
TrivialFileOperationsFactory::~TrivialFileOperationsFactory() = default;

std::unique_ptr<BackendFileOperations> TrivialFileOperationsFactory::Create(
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  return std::make_unique<TrivialFileOperations>();
}

std::unique_ptr<UnboundBackendFileOperations>
TrivialFileOperationsFactory::CreateUnbound() {
  return std::make_unique<UnboundTrivialFileOperations>();
}

}  // namespace disk_cache
