xref: /aosp_15_r20/external/cronet/net/disk_cache/disk_cache.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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