668 lines
21 KiB
C++
668 lines
21 KiB
C++
// 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
|