1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <utility>
6
7 #include "base/barrier_closure.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/task/bind_post_task.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/task/thread_pool/thread_pool_instance.h"
18 #include "build/build_config.h"
19 #include "net/base/cache_type.h"
20 #include "net/base/net_errors.h"
21 #include "net/disk_cache/backend_cleanup_tracker.h"
22 #include "net/disk_cache/blockfile/backend_impl.h"
23 #include "net/disk_cache/cache_util.h"
24 #include "net/disk_cache/disk_cache.h"
25 #include "net/disk_cache/memory/mem_backend_impl.h"
26 #include "net/disk_cache/simple/simple_backend_impl.h"
27 #include "net/disk_cache/simple/simple_file_enumerator.h"
28 #include "net/disk_cache/simple/simple_util.h"
29
30 namespace {
31
32 using FileEnumerator = disk_cache::BackendFileOperations::FileEnumerator;
33
34 // Builds an instance of the backend depending on platform, type, experiments
35 // etc. Takes care of the retry state. This object will self-destroy when
36 // finished.
37 class CacheCreator {
38 public:
39 CacheCreator(const base::FilePath& path,
40 disk_cache::ResetHandling reset_handling,
41 int64_t max_bytes,
42 net::CacheType type,
43 net::BackendType backend_type,
44 scoped_refptr<disk_cache::BackendFileOperationsFactory>
45 file_operations_factory,
46 #if BUILDFLAG(IS_ANDROID)
47 base::android::ApplicationStatusListener* app_status_listener,
48 #endif
49 net::NetLog* net_log,
50 base::OnceClosure post_cleanup_callback,
51 disk_cache::BackendResultCallback callback);
52
53 CacheCreator(const CacheCreator&) = delete;
54 CacheCreator& operator=(const CacheCreator&) = delete;
55
56 // Wait for any previous backends for given path to finish clean up and then
57 // attempt to create a new one. This will never succeed synchronously, though
58 // it may fail synchronously.
59 net::Error TryCreateCleanupTrackerAndRun();
60
61 // Creates the backend, the cleanup context for it having been already
62 // established... or purposefully left as null. This will never succeed
63 // synchronously, though it may fail synchronously.
64 net::Error Run();
65
66 private:
67 ~CacheCreator();
68
69 void DoCallback(int result);
70
71 void OnIOComplete(int result);
72 void OnCacheCleanupComplete(int original_error, bool cleanup_result);
73
74 const base::FilePath path_;
75 disk_cache::ResetHandling reset_handling_;
76 bool retry_ = false;
77 int64_t max_bytes_;
78 net::CacheType type_;
79 net::BackendType backend_type_;
80 scoped_refptr<disk_cache::BackendFileOperationsFactory>
81 file_operations_factory_;
82 std::unique_ptr<disk_cache::BackendFileOperations> file_operations_;
83 #if BUILDFLAG(IS_ANDROID)
84 raw_ptr<base::android::ApplicationStatusListener> app_status_listener_;
85 #endif
86 base::OnceClosure post_cleanup_callback_;
87 disk_cache::BackendResultCallback callback_;
88 std::unique_ptr<disk_cache::Backend> created_cache_;
89 raw_ptr<net::NetLog> net_log_;
90 scoped_refptr<disk_cache::BackendCleanupTracker> cleanup_tracker_;
91 };
92
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,base::android::ApplicationStatusListener * app_status_listener,net::NetLog * net_log,base::OnceClosure post_cleanup_callback,disk_cache::BackendResultCallback callback)93 CacheCreator::CacheCreator(
94 const base::FilePath& path,
95 disk_cache::ResetHandling reset_handling,
96 int64_t max_bytes,
97 net::CacheType type,
98 net::BackendType backend_type,
99 scoped_refptr<disk_cache::BackendFileOperationsFactory> file_operations,
100 #if BUILDFLAG(IS_ANDROID)
101 base::android::ApplicationStatusListener* app_status_listener,
102 #endif
103 net::NetLog* net_log,
104 base::OnceClosure post_cleanup_callback,
105 disk_cache::BackendResultCallback callback)
106 : path_(path),
107 reset_handling_(reset_handling),
108 max_bytes_(max_bytes),
109 type_(type),
110 backend_type_(backend_type),
111 file_operations_factory_(std::move(file_operations)),
112 #if BUILDFLAG(IS_ANDROID)
113 app_status_listener_(app_status_listener),
114 #endif
115 post_cleanup_callback_(std::move(post_cleanup_callback)),
116 callback_(std::move(callback)),
117 net_log_(net_log) {
118 }
119
120 CacheCreator::~CacheCreator() = default;
121
Run()122 net::Error CacheCreator::Run() {
123 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
124 static const bool kSimpleBackendIsDefault = true;
125 #else
126 static const bool kSimpleBackendIsDefault = false;
127 #endif
128 if (!retry_ && reset_handling_ == disk_cache::ResetHandling::kReset) {
129 // Pretend that we failed to create a cache, so that we can handle `kReset`
130 // and `kResetOnError` in a unified way, in CacheCreator::OnIOComplete.
131 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
132 FROM_HERE, base::BindOnce(&CacheCreator::OnIOComplete,
133 base::Unretained(this), net::ERR_FAILED));
134 return net::ERR_IO_PENDING;
135 }
136 if (backend_type_ == net::CACHE_BACKEND_SIMPLE ||
137 (backend_type_ == net::CACHE_BACKEND_DEFAULT &&
138 kSimpleBackendIsDefault)) {
139 auto cache = std::make_unique<disk_cache::SimpleBackendImpl>(
140 file_operations_factory_, path_, cleanup_tracker_.get(),
141 /* file_tracker = */ nullptr, max_bytes_, type_, net_log_);
142 disk_cache::SimpleBackendImpl* simple_cache = cache.get();
143 created_cache_ = std::move(cache);
144 #if BUILDFLAG(IS_ANDROID)
145 if (app_status_listener_)
146 simple_cache->set_app_status_listener(app_status_listener_);
147 #endif
148 simple_cache->Init(
149 base::BindOnce(&CacheCreator::OnIOComplete, base::Unretained(this)));
150 return net::ERR_IO_PENDING;
151 }
152
153 // Avoid references to blockfile functions on Android to reduce binary size.
154 #if BUILDFLAG(IS_ANDROID)
155 return net::ERR_FAILED;
156 #else
157 auto cache = std::make_unique<disk_cache::BackendImpl>(
158 path_, cleanup_tracker_.get(),
159 /*cache_thread = */ nullptr, type_, net_log_);
160 disk_cache::BackendImpl* new_cache = cache.get();
161 created_cache_ = std::move(cache);
162 new_cache->SetMaxSize(max_bytes_);
163 new_cache->Init(
164 base::BindOnce(&CacheCreator::OnIOComplete, base::Unretained(this)));
165 return net::ERR_IO_PENDING;
166 #endif
167 }
168
TryCreateCleanupTrackerAndRun()169 net::Error CacheCreator::TryCreateCleanupTrackerAndRun() {
170 // Before creating a cache Backend, a BackendCleanupTracker object is needed
171 // so there is a place to keep track of outstanding I/O even after the backend
172 // object itself is destroyed, so that further use of the directory
173 // doesn't race with those outstanding disk I/O ops.
174
175 // This method's purpose it to grab exlusive ownership of a fresh
176 // BackendCleanupTracker for the cache path, and then move on to Run(),
177 // which will take care of creating the actual cache backend. It's possible
178 // that something else is currently making use of the directory, in which
179 // case BackendCleanupTracker::TryCreate will fail, but will just have
180 // TryCreateCleanupTrackerAndRun run again at an opportune time to make
181 // another attempt.
182
183 // The resulting BackendCleanupTracker is stored into a scoped_refptr member
184 // so that it's kept alive while |this| CacheCreator exists , so that in the
185 // case Run() needs to retry Backend creation the same BackendCleanupTracker
186 // is used for both attempts, and |post_cleanup_callback_| gets called after
187 // the second try, not the first one.
188 cleanup_tracker_ = disk_cache::BackendCleanupTracker::TryCreate(
189 path_, base::BindOnce(base::IgnoreResult(
190 &CacheCreator::TryCreateCleanupTrackerAndRun),
191 base::Unretained(this)));
192 if (!cleanup_tracker_)
193 return net::ERR_IO_PENDING;
194 if (!post_cleanup_callback_.is_null())
195 cleanup_tracker_->AddPostCleanupCallback(std::move(post_cleanup_callback_));
196 return Run();
197 }
198
DoCallback(int net_error)199 void CacheCreator::DoCallback(int net_error) {
200 DCHECK_NE(net::ERR_IO_PENDING, net_error);
201 disk_cache::BackendResult result;
202 if (net_error == net::OK) {
203 result = disk_cache::BackendResult::Make(std::move(created_cache_));
204 } else {
205 LOG(ERROR) << "Unable to create cache";
206 result = disk_cache::BackendResult::MakeError(
207 static_cast<net::Error>(net_error));
208 created_cache_.reset();
209 }
210 std::move(callback_).Run(std::move(result));
211 delete this;
212 }
213
214 // If the initialization of the cache fails, and |reset_handling| isn't set to
215 // kNeverReset, we will discard the whole cache and create a new one.
OnIOComplete(int result)216 void CacheCreator::OnIOComplete(int result) {
217 DCHECK_NE(result, net::ERR_IO_PENDING);
218 if (result == net::OK ||
219 reset_handling_ == disk_cache::ResetHandling::kNeverReset || retry_) {
220 return DoCallback(result);
221 }
222
223 // We are supposed to try again, so delete the object and all files and do so.
224 retry_ = true;
225 created_cache_.reset();
226
227 if (!file_operations_) {
228 if (file_operations_factory_) {
229 file_operations_ = file_operations_factory_->Create(
230 base::SequencedTaskRunner::GetCurrentDefault());
231 } else {
232 file_operations_ = std::make_unique<disk_cache::TrivialFileOperations>();
233 }
234 }
235 file_operations_->CleanupDirectory(
236 path_, base::BindOnce(&CacheCreator::OnCacheCleanupComplete,
237 base::Unretained(this), result));
238 }
239
OnCacheCleanupComplete(int original_result,bool cleanup_result)240 void CacheCreator::OnCacheCleanupComplete(int original_result,
241 bool cleanup_result) {
242 if (!cleanup_result) {
243 // Cleaning up the cache directory fails, so this operation should be
244 // considered failed.
245 DCHECK_NE(original_result, net::OK);
246 DCHECK_NE(original_result, net::ERR_IO_PENDING);
247 DoCallback(original_result);
248 return;
249 }
250
251 // The worker thread may be deleting files, but the original folder
252 // is not there anymore... let's create a new set of files.
253 int rv = Run();
254 DCHECK_EQ(net::ERR_IO_PENDING, rv);
255 }
256
257 class TrivialFileEnumerator final : public FileEnumerator {
258 public:
259 using FileEnumerationEntry =
260 disk_cache::BackendFileOperations::FileEnumerationEntry;
261
TrivialFileEnumerator(const base::FilePath & path)262 explicit TrivialFileEnumerator(const base::FilePath& path)
263 : enumerator_(path) {}
264 ~TrivialFileEnumerator() override = default;
265
Next()266 absl::optional<FileEnumerationEntry> Next() override {
267 return enumerator_.Next();
268 }
HasError() const269 bool HasError() const override { return enumerator_.HasError(); }
270
271 private:
272 disk_cache::SimpleFileEnumerator enumerator_;
273 };
274
275 class UnboundTrivialFileOperations
276 : public disk_cache::UnboundBackendFileOperations {
277 public:
Bind(scoped_refptr<base::SequencedTaskRunner> task_runner)278 std::unique_ptr<disk_cache::BackendFileOperations> Bind(
279 scoped_refptr<base::SequencedTaskRunner> task_runner) override {
280 return std::make_unique<disk_cache::TrivialFileOperations>();
281 }
282 };
283
284 } // namespace
285
286 namespace disk_cache {
287
288 BackendResult::BackendResult() = default;
289 BackendResult::~BackendResult() = default;
290 BackendResult::BackendResult(BackendResult&&) = default;
291 BackendResult& BackendResult::operator=(BackendResult&&) = default;
292
293 // static
MakeError(net::Error error_in)294 BackendResult BackendResult::MakeError(net::Error error_in) {
295 DCHECK_NE(error_in, net::OK);
296 BackendResult result;
297 result.net_error = error_in;
298 return result;
299 }
300
301 // static
Make(std::unique_ptr<Backend> backend_in)302 BackendResult BackendResult::Make(std::unique_ptr<Backend> backend_in) {
303 DCHECK(backend_in);
304 BackendResult result;
305 result.net_error = net::OK;
306 result.backend = std::move(backend_in);
307 return result;
308 }
309
CreateCacheBackendImpl(net::CacheType type,net::BackendType backend_type,scoped_refptr<BackendFileOperationsFactory> file_operations,const base::FilePath & path,int64_t max_bytes,ResetHandling reset_handling,base::android::ApplicationStatusListener * app_status_listener,net::NetLog * net_log,base::OnceClosure post_cleanup_callback,BackendResultCallback callback)310 BackendResult CreateCacheBackendImpl(
311 net::CacheType type,
312 net::BackendType backend_type,
313 scoped_refptr<BackendFileOperationsFactory> file_operations,
314 const base::FilePath& path,
315 int64_t max_bytes,
316 ResetHandling reset_handling,
317 #if BUILDFLAG(IS_ANDROID)
318 base::android::ApplicationStatusListener* app_status_listener,
319 #endif
320 net::NetLog* net_log,
321 base::OnceClosure post_cleanup_callback,
322 BackendResultCallback callback) {
323 DCHECK(!callback.is_null());
324
325 if (type == net::MEMORY_CACHE) {
326 std::unique_ptr<MemBackendImpl> mem_backend_impl =
327 disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log);
328 if (mem_backend_impl) {
329 mem_backend_impl->SetPostCleanupCallback(
330 std::move(post_cleanup_callback));
331 return BackendResult::Make(std::move(mem_backend_impl));
332 } else {
333 if (!post_cleanup_callback.is_null())
334 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
335 FROM_HERE, std::move(post_cleanup_callback));
336 return BackendResult::MakeError(net::ERR_FAILED);
337 }
338 }
339
340 bool had_post_cleanup_callback = !post_cleanup_callback.is_null();
341 CacheCreator* creator = new CacheCreator(
342 path, reset_handling, max_bytes, type, backend_type,
343 std::move(file_operations),
344 #if BUILDFLAG(IS_ANDROID)
345 std::move(app_status_listener),
346 #endif
347 net_log, std::move(post_cleanup_callback), std::move(callback));
348 if (type == net::DISK_CACHE) {
349 DCHECK(!had_post_cleanup_callback);
350 return BackendResult::MakeError(creator->Run());
351 }
352
353 return BackendResult::MakeError(creator->TryCreateCleanupTrackerAndRun());
354 }
355
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)356 BackendResult CreateCacheBackend(
357 net::CacheType type,
358 net::BackendType backend_type,
359 scoped_refptr<BackendFileOperationsFactory> file_operations,
360 const base::FilePath& path,
361 int64_t max_bytes,
362 ResetHandling reset_handling,
363 net::NetLog* net_log,
364 BackendResultCallback callback) {
365 return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
366 path, max_bytes, reset_handling,
367 #if BUILDFLAG(IS_ANDROID)
368 nullptr,
369 #endif
370 net_log, base::OnceClosure(),
371 std::move(callback));
372 }
373
374 #if BUILDFLAG(IS_ANDROID)
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)375 NET_EXPORT BackendResult CreateCacheBackend(
376 net::CacheType type,
377 net::BackendType backend_type,
378 scoped_refptr<BackendFileOperationsFactory> file_operations,
379 const base::FilePath& path,
380 int64_t max_bytes,
381 ResetHandling reset_handling,
382 net::NetLog* net_log,
383 BackendResultCallback callback,
384 base::android::ApplicationStatusListener* app_status_listener) {
385 return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
386 path, max_bytes, reset_handling,
387 std::move(app_status_listener), net_log,
388 base::OnceClosure(), std::move(callback));
389 }
390 #endif
391
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)392 BackendResult CreateCacheBackend(
393 net::CacheType type,
394 net::BackendType backend_type,
395 scoped_refptr<BackendFileOperationsFactory> file_operations,
396 const base::FilePath& path,
397 int64_t max_bytes,
398 ResetHandling reset_handling,
399 net::NetLog* net_log,
400 base::OnceClosure post_cleanup_callback,
401 BackendResultCallback callback) {
402 return CreateCacheBackendImpl(type, backend_type, std::move(file_operations),
403 path, max_bytes, reset_handling,
404 #if BUILDFLAG(IS_ANDROID)
405 nullptr,
406 #endif
407 net_log, std::move(post_cleanup_callback),
408 std::move(callback));
409 }
410
FlushCacheThreadForTesting()411 void FlushCacheThreadForTesting() {
412 // For simple backend.
413 base::ThreadPoolInstance::Get()->FlushForTesting();
414
415 // Block backend.
416 BackendImpl::FlushForTesting();
417 }
418
FlushCacheThreadAsynchronouslyForTesting(base::OnceClosure callback)419 void FlushCacheThreadAsynchronouslyForTesting(base::OnceClosure callback) {
420 auto repeating_callback = base::BarrierClosure(2, std::move(callback));
421
422 // For simple backend.
423 base::ThreadPoolInstance::Get()->FlushAsyncForTesting( // IN-TEST
424 base::BindPostTaskToCurrentDefault(repeating_callback));
425
426 // Block backend.
427 BackendImpl::FlushAsynchronouslyForTesting(repeating_callback);
428 }
429
CalculateSizeOfEntriesBetween(base::Time initial_time,base::Time end_time,Int64CompletionOnceCallback callback)430 int64_t Backend::CalculateSizeOfEntriesBetween(
431 base::Time initial_time,
432 base::Time end_time,
433 Int64CompletionOnceCallback callback) {
434 return net::ERR_NOT_IMPLEMENTED;
435 }
436
GetEntryInMemoryData(const std::string & key)437 uint8_t Backend::GetEntryInMemoryData(const std::string& key) {
438 return 0;
439 }
440
SetEntryInMemoryData(const std::string & key,uint8_t data)441 void Backend::SetEntryInMemoryData(const std::string& key, uint8_t data) {}
442
443 EntryResult::EntryResult() = default;
444 EntryResult::~EntryResult() = default;
445
EntryResult(EntryResult && other)446 EntryResult::EntryResult(EntryResult&& other) {
447 net_error_ = other.net_error_;
448 entry_ = std::move(other.entry_);
449 opened_ = other.opened_;
450
451 other.net_error_ = net::ERR_FAILED;
452 other.opened_ = false;
453 }
454
operator =(EntryResult && other)455 EntryResult& EntryResult::operator=(EntryResult&& other) {
456 net_error_ = other.net_error_;
457 entry_ = std::move(other.entry_);
458 opened_ = other.opened_;
459
460 other.net_error_ = net::ERR_FAILED;
461 other.opened_ = false;
462 return *this;
463 }
464
465 // static
MakeOpened(Entry * new_entry)466 EntryResult EntryResult::MakeOpened(Entry* new_entry) {
467 DCHECK(new_entry);
468
469 EntryResult result;
470 result.net_error_ = net::OK;
471 result.entry_.reset(new_entry);
472 result.opened_ = true;
473 return result;
474 }
475
476 // static
MakeCreated(Entry * new_entry)477 EntryResult EntryResult::MakeCreated(Entry* new_entry) {
478 DCHECK(new_entry);
479
480 EntryResult result;
481 result.net_error_ = net::OK;
482 result.entry_.reset(new_entry);
483 result.opened_ = false;
484 return result;
485 }
486
487 // static
MakeError(net::Error status)488 EntryResult EntryResult::MakeError(net::Error status) {
489 DCHECK_NE(status, net::OK);
490
491 EntryResult result;
492 result.net_error_ = status;
493 return result;
494 }
495
ReleaseEntry()496 Entry* EntryResult::ReleaseEntry() {
497 Entry* ret = entry_.release();
498 net_error_ = net::ERR_FAILED;
499 opened_ = false;
500 return ret;
501 }
502
TrivialFileOperations()503 TrivialFileOperations::TrivialFileOperations() {
504 DETACH_FROM_SEQUENCE(sequence_checker_);
505 }
506
~TrivialFileOperations()507 TrivialFileOperations::~TrivialFileOperations() {
508 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
509 }
510
CreateDirectory(const base::FilePath & path)511 bool TrivialFileOperations::CreateDirectory(const base::FilePath& path) {
512 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
513 #if DCHECK_IS_ON()
514 DCHECK(bound_);
515 #endif
516
517 // This is needed for some unittests.
518 if (path.empty()) {
519 return false;
520 }
521
522 DCHECK(path.IsAbsolute());
523
524 bool result = base::CreateDirectory(path);
525 return result;
526 }
527
PathExists(const base::FilePath & path)528 bool TrivialFileOperations::PathExists(const base::FilePath& path) {
529 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
530 #if DCHECK_IS_ON()
531 DCHECK(bound_);
532 #endif
533
534 // This is needed for some unittests.
535 if (path.empty()) {
536 return false;
537 }
538
539 DCHECK(path.IsAbsolute());
540
541 bool result = base::PathExists(path);
542 return result;
543 }
544
DirectoryExists(const base::FilePath & path)545 bool TrivialFileOperations::DirectoryExists(const base::FilePath& path) {
546 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
547 DCHECK(path.IsAbsolute());
548 #if DCHECK_IS_ON()
549 DCHECK(bound_);
550 #endif
551
552 bool result = base::DirectoryExists(path);
553 return result;
554 }
555
OpenFile(const base::FilePath & path,uint32_t flags)556 base::File TrivialFileOperations::OpenFile(const base::FilePath& path,
557 uint32_t flags) {
558 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
559 DCHECK(path.IsAbsolute());
560 #if DCHECK_IS_ON()
561 DCHECK(bound_);
562 #endif
563
564 base::File file(path, flags);
565 return file;
566 }
567
DeleteFile(const base::FilePath & path,DeleteFileMode mode)568 bool TrivialFileOperations::DeleteFile(const base::FilePath& path,
569 DeleteFileMode mode) {
570 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
571 DCHECK(path.IsAbsolute());
572 #if DCHECK_IS_ON()
573 DCHECK(bound_);
574 #endif
575
576 bool result = false;
577 switch (mode) {
578 case DeleteFileMode::kDefault:
579 result = base::DeleteFile(path);
580 break;
581 case DeleteFileMode::kEnsureImmediateAvailability:
582 result = disk_cache::simple_util::SimpleCacheDeleteFile(path);
583 break;
584 }
585 return result;
586 }
587
ReplaceFile(const base::FilePath & from_path,const base::FilePath & to_path,base::File::Error * error)588 bool TrivialFileOperations::ReplaceFile(const base::FilePath& from_path,
589 const base::FilePath& to_path,
590 base::File::Error* error) {
591 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
592 DCHECK(from_path.IsAbsolute());
593 DCHECK(to_path.IsAbsolute());
594 #if DCHECK_IS_ON()
595 DCHECK(bound_);
596 #endif
597
598 return base::ReplaceFile(from_path, to_path, error);
599 }
600
GetFileInfo(const base::FilePath & path)601 absl::optional<base::File::Info> TrivialFileOperations::GetFileInfo(
602 const base::FilePath& path) {
603 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
604 DCHECK(path.IsAbsolute());
605 #if DCHECK_IS_ON()
606 DCHECK(bound_);
607 #endif
608
609 base::File::Info file_info;
610 if (!base::GetFileInfo(path, &file_info)) {
611 return absl::nullopt;
612 }
613 return file_info;
614 }
615
EnumerateFiles(const base::FilePath & path)616 std::unique_ptr<FileEnumerator> TrivialFileOperations::EnumerateFiles(
617 const base::FilePath& path) {
618 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
619 DCHECK(path.IsAbsolute());
620 #if DCHECK_IS_ON()
621 DCHECK(bound_);
622 #endif
623 return std::make_unique<TrivialFileEnumerator>(path);
624 }
625
CleanupDirectory(const base::FilePath & path,base::OnceCallback<void (bool)> callback)626 void TrivialFileOperations::CleanupDirectory(
627 const base::FilePath& path,
628 base::OnceCallback<void(bool)> callback) {
629 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
630
631 // This is needed for some unittests.
632 if (path.empty()) {
633 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
634 FROM_HERE, base::BindOnce(std::move(callback), false));
635 return;
636 }
637
638 DCHECK(path.IsAbsolute());
639 #if DCHECK_IS_ON()
640 DCHECK(bound_);
641 #endif
642
643 disk_cache::CleanupDirectory(path, std::move(callback));
644 }
645
Unbind()646 std::unique_ptr<UnboundBackendFileOperations> TrivialFileOperations::Unbind() {
647 #if DCHECK_IS_ON()
648 DCHECK(bound_);
649 bound_ = false;
650 #endif
651 return std::make_unique<UnboundTrivialFileOperations>();
652 }
653
654 TrivialFileOperationsFactory::TrivialFileOperationsFactory() = default;
655 TrivialFileOperationsFactory::~TrivialFileOperationsFactory() = default;
656
Create(scoped_refptr<base::SequencedTaskRunner> task_runner)657 std::unique_ptr<BackendFileOperations> TrivialFileOperationsFactory::Create(
658 scoped_refptr<base::SequencedTaskRunner> task_runner) {
659 return std::make_unique<TrivialFileOperations>();
660 }
661
662 std::unique_ptr<UnboundBackendFileOperations>
CreateUnbound()663 TrivialFileOperationsFactory::CreateUnbound() {
664 return std::make_unique<UnboundTrivialFileOperations>();
665 }
666
667 } // namespace disk_cache
668