OLD | NEW |
| (Empty) |
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 #include "webkit/fileapi/recursive_operation_delegate.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "webkit/fileapi/file_system_context.h" | |
9 #include "webkit/fileapi/file_system_operation_context.h" | |
10 #include "webkit/fileapi/local_file_system_operation.h" | |
11 | |
12 namespace fileapi { | |
13 | |
14 namespace { | |
15 // Don't start too many inflight operations. | |
16 const int kMaxInflightOperations = 5; | |
17 } | |
18 | |
19 RecursiveOperationDelegate::RecursiveOperationDelegate( | |
20 FileSystemContext* file_system_context, | |
21 LocalFileSystemOperation* operation) | |
22 : file_system_context_(file_system_context), | |
23 operation_(operation), | |
24 inflight_operations_(0) { | |
25 } | |
26 | |
27 RecursiveOperationDelegate::~RecursiveOperationDelegate() { | |
28 } | |
29 | |
30 void RecursiveOperationDelegate::StartRecursiveOperation( | |
31 const FileSystemURL& root, | |
32 const StatusCallback& callback) { | |
33 callback_ = callback; | |
34 pending_directories_.push(root); | |
35 ProcessNextDirectory(); | |
36 } | |
37 | |
38 LocalFileSystemOperation* RecursiveOperationDelegate::NewNestedOperation() { | |
39 return operation_->CreateNestedOperation(); | |
40 } | |
41 | |
42 void RecursiveOperationDelegate::ProcessNextDirectory() { | |
43 DCHECK(pending_files_.empty()); | |
44 if (inflight_operations_ > 0) | |
45 return; | |
46 if (pending_directories_.empty()) { | |
47 callback_.Run(base::PLATFORM_FILE_OK); | |
48 return; | |
49 } | |
50 FileSystemURL url = pending_directories_.front(); | |
51 pending_directories_.pop(); | |
52 inflight_operations_++; | |
53 ProcessDirectory( | |
54 url, base::Bind(&RecursiveOperationDelegate::DidProcessDirectory, | |
55 AsWeakPtr(), url)); | |
56 } | |
57 | |
58 void RecursiveOperationDelegate::ProcessPendingFiles() { | |
59 if (pending_files_.empty()) { | |
60 ProcessNextDirectory(); | |
61 return; | |
62 } | |
63 while (!pending_files_.empty() && | |
64 inflight_operations_ < kMaxInflightOperations) { | |
65 FileSystemURL url = pending_files_.front(); | |
66 pending_files_.pop(); | |
67 inflight_operations_++; | |
68 base::MessageLoopProxy::current()->PostTask( | |
69 FROM_HERE, | |
70 base::Bind(&RecursiveOperationDelegate::ProcessFile, | |
71 AsWeakPtr(), url, | |
72 base::Bind(&RecursiveOperationDelegate::DidProcessFile, | |
73 AsWeakPtr()))); | |
74 } | |
75 } | |
76 | |
77 void RecursiveOperationDelegate::DidProcessFile(base::PlatformFileError error) { | |
78 inflight_operations_--; | |
79 DCHECK_GE(inflight_operations_, 0); | |
80 if (error != base::PLATFORM_FILE_OK) { | |
81 callback_.Run(error); | |
82 return; | |
83 } | |
84 ProcessPendingFiles(); | |
85 } | |
86 | |
87 void RecursiveOperationDelegate::DidProcessDirectory( | |
88 const FileSystemURL& url, | |
89 base::PlatformFileError error) { | |
90 if (error != base::PLATFORM_FILE_OK) { | |
91 callback_.Run(error); | |
92 return; | |
93 } | |
94 NewNestedOperation()->ReadDirectory( | |
95 url, base::Bind(&RecursiveOperationDelegate::DidReadDirectory, | |
96 AsWeakPtr(), url)); | |
97 } | |
98 | |
99 void RecursiveOperationDelegate::DidReadDirectory( | |
100 const FileSystemURL& parent, | |
101 base::PlatformFileError error, | |
102 const FileEntryList& entries, | |
103 bool has_more) { | |
104 if (error != base::PLATFORM_FILE_OK) { | |
105 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { | |
106 // The given path may have been a file, so try RemoveFile now. | |
107 ProcessFile(parent, | |
108 base::Bind(&RecursiveOperationDelegate::DidTryProcessFile, | |
109 AsWeakPtr(), error)); | |
110 return; | |
111 } | |
112 callback_.Run(error); | |
113 return; | |
114 } | |
115 for (size_t i = 0; i < entries.size(); i++) { | |
116 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( | |
117 parent.origin(), | |
118 parent.mount_type(), | |
119 parent.virtual_path().Append(entries[i].name)); | |
120 if (entries[i].is_directory) | |
121 pending_directories_.push(url); | |
122 else | |
123 pending_files_.push(url); | |
124 } | |
125 if (has_more) | |
126 return; | |
127 | |
128 inflight_operations_--; | |
129 DCHECK_GE(inflight_operations_, 0); | |
130 ProcessPendingFiles(); | |
131 } | |
132 | |
133 void RecursiveOperationDelegate::DidTryProcessFile( | |
134 base::PlatformFileError previous_error, | |
135 base::PlatformFileError error) { | |
136 if (error == base::PLATFORM_FILE_ERROR_NOT_A_FILE) { | |
137 // It wasn't a file either; returns with the previous error. | |
138 callback_.Run(previous_error); | |
139 return; | |
140 } | |
141 DidProcessFile(error); | |
142 } | |
143 | |
144 } // namespace fileapi | |
OLD | NEW |