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