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