• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #ifndef WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_
6 #define WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_
7 
8 #include <queue>
9 #include <stack>
10 
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/memory/weak_ptr.h"
14 #include "webkit/browser/fileapi/file_system_operation.h"
15 #include "webkit/browser/fileapi/file_system_url.h"
16 
17 namespace fileapi {
18 
19 class FileSystemContext;
20 class FileSystemOperationRunner;
21 
22 // A base class for recursive operation delegates.
23 //
24 // In short, each subclass should override ProcessFile and ProcessDirectory
25 // to process a directory or a file. To start the recursive operation it
26 // should also call StartRecursiveOperation.
27 class WEBKIT_STORAGE_BROWSER_EXPORT RecursiveOperationDelegate
28     : public base::SupportsWeakPtr<RecursiveOperationDelegate> {
29  public:
30   typedef FileSystemOperation::StatusCallback StatusCallback;
31   typedef FileSystemOperation::FileEntryList FileEntryList;
32 
33   virtual ~RecursiveOperationDelegate();
34 
35   // This is called when the consumer of this instance starts a non-recursive
36   // operation.
37   virtual void Run() = 0;
38 
39   // This is called when the consumer of this instance starts a recursive
40   // operation.
41   virtual void RunRecursively() = 0;
42 
43   // This is called each time a file is found while recursively
44   // performing an operation.
45   virtual void ProcessFile(const FileSystemURL& url,
46                            const StatusCallback& callback) = 0;
47 
48   // This is called each time a directory is found while recursively
49   // performing an operation.
50   virtual void ProcessDirectory(const FileSystemURL& url,
51                                 const StatusCallback& callback) = 0;
52 
53 
54   // This is called each time after files and subdirectories for a
55   // directory is processed while recursively performing an operation.
56   virtual void PostProcessDirectory(const FileSystemURL& url,
57                                     const StatusCallback& callback) = 0;
58 
59   // Cancels the currently running operation.
60   void Cancel();
61 
62  protected:
63   explicit RecursiveOperationDelegate(FileSystemContext* file_system_context);
64 
65   // Starts to process files/directories recursively from the given |root|.
66   // This will call ProcessFile and ProcessDirectory on each file or directory.
67   //
68   // First, this tries to call ProcessFile with |root| regardless whether it is
69   // actually a file or a directory. If it is a directory, ProcessFile should
70   // return PLATFORM_FILE_NOT_A_FILE.
71   //
72   // For each directory, the recursive operation works as follows:
73   // ProcessDirectory is called first for the directory.
74   // Then the directory contents are read (to obtain its sub directories and
75   // files in it).
76   // ProcessFile is called for found files. This may run in parallel.
77   // The same step is recursively applied to each subdirectory.
78   // After all files and subdirectories in a directory are processed,
79   // PostProcessDirectory is called for the directory.
80   // Here is an example;
81   // a_dir/ -+- b1_dir/ -+- c1_dir/ -+- d1_file
82   //         |           |           |
83   //         |           +- c2_file  +- d2_file
84   //         |
85   //         +- b2_dir/ --- e_dir/
86   //         |
87   //         +- b3_file
88   //         |
89   //         +- b4_file
90   // Then traverse order is:
91   // ProcessFile(a_dir) (This should return PLATFORM_FILE_NOT_A_FILE).
92   // ProcessDirectory(a_dir).
93   // ProcessFile(b3_file), ProcessFile(b4_file). (in parallel).
94   // ProcessDirectory(b1_dir).
95   // ProcessFile(c2_file)
96   // ProcessDirectory(c1_dir).
97   // ProcessFile(d1_file), ProcessFile(d2_file). (in parallel).
98   // PostProcessDirectory(c1_dir)
99   // PostProcessDirectory(b1_dir).
100   // ProcessDirectory(b2_dir)
101   // ProcessDirectory(e_dir)
102   // PostProcessDirectory(e_dir)
103   // PostProcessDirectory(b2_dir)
104   // PostProcessDirectory(a_dir)
105   //
106   // |callback| is fired with base::PLATFORM_FILE_OK when every file/directory
107   // under |root| is processed, or fired earlier when any suboperation fails.
108   void StartRecursiveOperation(const FileSystemURL& root,
109                                const StatusCallback& callback);
110 
file_system_context()111   FileSystemContext* file_system_context() { return file_system_context_; }
file_system_context()112   const FileSystemContext* file_system_context() const {
113     return file_system_context_;
114   }
115 
116   FileSystemOperationRunner* operation_runner();
117 
118   // Called when Cancel() is called. This is a hook to do something more
119   // in a derived class. By default, do nothing.
120   virtual void OnCancel();
121 
122  private:
123   void DidTryProcessFile(const FileSystemURL& root,
124                          base::PlatformFileError error);
125   void ProcessNextDirectory();
126   void DidProcessDirectory(base::PlatformFileError error);
127   void DidReadDirectory(const FileSystemURL& parent,
128                         base::PlatformFileError error,
129                         const FileEntryList& entries,
130                         bool has_more);
131   void ProcessPendingFiles();
132   void DidProcessFile(base::PlatformFileError error);
133   void ProcessSubDirectory();
134   void DidPostProcessDirectory(base::PlatformFileError error);
135 
136   // Called when all recursive operation is done (or an error occurs).
137   void Done(base::PlatformFileError error);
138 
139   FileSystemContext* file_system_context_;
140   StatusCallback callback_;
141   std::stack<FileSystemURL> pending_directories_;
142   std::stack<std::queue<FileSystemURL> > pending_directory_stack_;
143   std::queue<FileSystemURL> pending_files_;
144   int inflight_operations_;
145   bool canceled_;
146 
147   DISALLOW_COPY_AND_ASSIGN(RecursiveOperationDelegate);
148 };
149 
150 }  // namespace fileapi
151 
152 #endif  // WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_
153