• 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 
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