recursive_operation_delegate.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef STORAGE_BROWSER_FILE_SYSTEM_RECURSIVE_OPERATION_DELEGATE_H_
  5. #define STORAGE_BROWSER_FILE_SYSTEM_RECURSIVE_OPERATION_DELEGATE_H_
  6. #include "base/callback.h"
  7. #include "base/component_export.h"
  8. #include "base/containers/queue.h"
  9. #include "base/containers/stack.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "storage/browser/file_system/file_system_operation.h"
  13. #include "storage/browser/file_system/file_system_url.h"
  14. namespace storage {
  15. class FileSystemContext;
  16. class FileSystemOperationRunner;
  17. // A base class for recursive operation delegates.
  18. //
  19. // In short, each subclass should override ProcessFile and ProcessDirectory
  20. // to process a directory or a file. To start the recursive operation it
  21. // should also call StartRecursiveOperation.
  22. class COMPONENT_EXPORT(STORAGE_BROWSER) RecursiveOperationDelegate
  23. : public base::SupportsWeakPtr<RecursiveOperationDelegate> {
  24. public:
  25. using StatusCallback = FileSystemOperation::StatusCallback;
  26. using FileEntryList = FileSystemOperation::FileEntryList;
  27. using ErrorBehavior = FileSystemOperation::ErrorBehavior;
  28. RecursiveOperationDelegate(const RecursiveOperationDelegate&) = delete;
  29. RecursiveOperationDelegate& operator=(const RecursiveOperationDelegate&) =
  30. delete;
  31. virtual ~RecursiveOperationDelegate();
  32. // This is called when the consumer of this instance starts a non-recursive
  33. // operation.
  34. virtual void Run() = 0;
  35. // This is called when the consumer of this instance starts a recursive
  36. // operation.
  37. virtual void RunRecursively() = 0;
  38. // This is called each time a file is found while recursively
  39. // performing an operation.
  40. virtual void ProcessFile(const FileSystemURL& url,
  41. StatusCallback callback) = 0;
  42. // This is called each time a directory is found while recursively
  43. // performing an operation.
  44. virtual void ProcessDirectory(const FileSystemURL& url,
  45. StatusCallback callback) = 0;
  46. // This is called each time after files and subdirectories for a
  47. // directory is processed while recursively performing an operation.
  48. virtual void PostProcessDirectory(const FileSystemURL& url,
  49. StatusCallback callback) = 0;
  50. // Cancels the currently running operation.
  51. void Cancel();
  52. protected:
  53. explicit RecursiveOperationDelegate(FileSystemContext* file_system_context);
  54. // Starts to process files/directories recursively from the given `root`.
  55. // This will call ProcessFile and ProcessDirectory on each file or directory.
  56. //
  57. // First, this tries to call ProcessFile with `root` regardless whether it is
  58. // actually a file or a directory. If it is a directory, ProcessFile should
  59. // return File::FILE_NOT_A_FILE.
  60. //
  61. // For each directory, the recursive operation works as follows:
  62. // ProcessDirectory is called first for the directory.
  63. // Then the directory contents are read (to obtain its sub directories and
  64. // files in it).
  65. // ProcessFile is called for found files.
  66. // The same step is recursively applied to each subdirectory.
  67. // After all files and subdirectories in a directory are processed,
  68. // PostProcessDirectory is called for the directory.
  69. // Here is an example;
  70. // a_dir/ -+- b1_dir/ -+- c1_dir/ -+- d1_file
  71. // | | |
  72. // | +- c2_file +- d2_file
  73. // |
  74. // +- b2_dir/ --- e_dir/
  75. // |
  76. // +- b3_file
  77. // |
  78. // +- b4_file
  79. // Then traverse order is:
  80. // ProcessFile(a_dir) (This should return File::FILE_NOT_A_FILE).
  81. // ProcessDirectory(a_dir).
  82. // ProcessFile(b3_file).
  83. // ProcessFile(b4_file).
  84. // ProcessDirectory(b1_dir).
  85. // ProcessFile(c2_file)
  86. // ProcessDirectory(c1_dir).
  87. // ProcessFile(d1_file).
  88. // ProcessFile(d2_file).
  89. // PostProcessDirectory(c1_dir)
  90. // PostProcessDirectory(b1_dir).
  91. // ProcessDirectory(b2_dir)
  92. // ProcessDirectory(e_dir)
  93. // PostProcessDirectory(e_dir)
  94. // PostProcessDirectory(b2_dir)
  95. // PostProcessDirectory(a_dir)
  96. //
  97. // `error_behavior` is to specify how this behaves when an operation have
  98. // failed.
  99. // `callback` is fired with `base::File::FILE_OK` when every file/directory
  100. // under `root` is processed, or fired earlier when any suboperation fails.
  101. //
  102. // For `ERROR_BEHAVIOR_SKIP`, `callback` is fired at the end of the operation
  103. // or when an unrecoverable error occurs. `callback` is called with the last
  104. // error or `base::File::FILE_OK` if no error occurred.
  105. void StartRecursiveOperation(const FileSystemURL& root,
  106. ErrorBehavior error_behavior,
  107. StatusCallback callback);
  108. FileSystemContext* file_system_context() { return file_system_context_; }
  109. const FileSystemContext* file_system_context() const {
  110. return file_system_context_;
  111. }
  112. FileSystemOperationRunner* operation_runner();
  113. // Called when Cancel() is called. This is a hook to do something more
  114. // in a derived class. By default, do nothing.
  115. virtual void OnCancel();
  116. private:
  117. void TryProcessFile(const FileSystemURL& root);
  118. void DidTryProcessFile(const FileSystemURL& root, base::File::Error error);
  119. void ProcessNextDirectory();
  120. void DidProcessDirectory(base::File::Error error);
  121. void DidReadDirectory(const FileSystemURL& parent,
  122. base::File::Error error,
  123. FileEntryList entries,
  124. bool has_more);
  125. void ProcessPendingFiles();
  126. void DidProcessFile(const FileSystemURL& url, base::File::Error error);
  127. void ProcessSubDirectory();
  128. void DidPostProcessDirectory(base::File::Error error);
  129. void SetPreviousError(base::File::Error error);
  130. // Called when all recursive operation is done (or an error occurs).
  131. void Done(base::File::Error error);
  132. raw_ptr<FileSystemContext, DanglingUntriaged> file_system_context_;
  133. StatusCallback callback_;
  134. base::stack<FileSystemURL> pending_directories_;
  135. base::stack<base::queue<FileSystemURL>> pending_directory_stack_;
  136. base::queue<FileSystemURL> pending_files_;
  137. bool canceled_ = false;
  138. ErrorBehavior error_behavior_ = ErrorBehavior::ERROR_BEHAVIOR_ABORT;
  139. base::File::Error previous_error_ = base::File::FILE_OK;
  140. };
  141. } // namespace storage
  142. #endif // STORAGE_BROWSER_FILE_SYSTEM_RECURSIVE_OPERATION_DELEGATE_H_