OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/fileapi/cross_operation_delegate.h" | 5 #include "webkit/fileapi/cross_operation_delegate.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "webkit/blob/shareable_file_reference.h" | 8 #include "webkit/blob/shareable_file_reference.h" |
9 #include "webkit/fileapi/copy_or_move_file_validator.h" | 9 #include "webkit/fileapi/copy_or_move_file_validator.h" |
10 #include "webkit/fileapi/file_system_context.h" | 10 #include "webkit/fileapi/file_system_context.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 return; | 48 return; |
49 } | 49 } |
50 | 50 |
51 // It is an error to copy/move an entry into the same path. | 51 // It is an error to copy/move an entry into the same path. |
52 if (same_file_system_ && src_root_.path() == dest_root_.path()) { | 52 if (same_file_system_ && src_root_.path() == dest_root_.path()) { |
53 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); | 53 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); |
54 return; | 54 return; |
55 } | 55 } |
56 | 56 |
57 // First try to copy/move it as a file. | 57 // First try to copy/move it as a file. |
58 CopyOrMoveFile(src_root_, dest_root_, | 58 Request request(src_root_, dest_root_, |
59 base::Bind(&CrossOperationDelegate::DidTryCopyOrMoveFile, | 59 base::Bind(&CrossOperationDelegate::DidTryCopyOrMoveFile, |
60 AsWeakPtr())); | 60 AsWeakPtr())); |
| 61 CopyOrMoveFile(request); |
61 } | 62 } |
62 | 63 |
63 void CrossOperationDelegate::ProcessFile(const FileSystemURL& src_url, | 64 void CrossOperationDelegate::ProcessFile(const FileSystemURL& src_url, |
64 const StatusCallback& callback) { | 65 const StatusCallback& callback) { |
65 CopyOrMoveFile(src_url, CreateDestURL(src_url), callback); | 66 Request request(src_url, CreateDestURL(src_url), callback); |
| 67 CopyOrMoveFile(request); |
66 } | 68 } |
67 | 69 |
68 void CrossOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, | 70 void CrossOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, |
69 const StatusCallback& callback) { | 71 const StatusCallback& callback) { |
70 FileSystemURL dest_url = CreateDestURL(src_url); | 72 FileSystemURL dest_url = CreateDestURL(src_url); |
71 | 73 |
72 // If operation_type == Move we may need to record directories and | 74 // If operation_type == Move we may need to record directories and |
73 // restore directory timestamps in the end, though it may have | 75 // restore directory timestamps in the end, though it may have |
74 // negative performance impact. | 76 // negative performance impact. |
75 // See http://crbug.com/171284 for more details. | 77 // See http://crbug.com/171284 for more details. |
(...skipping 26 matching lines...) Expand all Loading... |
102 if (error != base::PLATFORM_FILE_OK && | 104 if (error != base::PLATFORM_FILE_OK && |
103 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { | 105 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
104 callback_.Run(error); | 106 callback_.Run(error); |
105 return; | 107 return; |
106 } | 108 } |
107 | 109 |
108 // Start to process the source directory recursively. | 110 // Start to process the source directory recursively. |
109 // TODO(kinuko): This could be too expensive for same_file_system_==true | 111 // TODO(kinuko): This could be too expensive for same_file_system_==true |
110 // and operation==MOVE case, probably we can just rename the root directory. | 112 // and operation==MOVE case, probably we can just rename the root directory. |
111 // http://crbug.com/172187 | 113 // http://crbug.com/172187 |
| 114 Request request(src_root_, dest_root_, callback_); |
112 StartRecursiveOperation( | 115 StartRecursiveOperation( |
113 src_root_, base::Bind(&CrossOperationDelegate::DidFinishCopy, | 116 src_root_, base::Bind(&CrossOperationDelegate::DidFinishCopy, |
114 AsWeakPtr(), src_root_, callback_)); | 117 AsWeakPtr(), request)); |
115 } | 118 } |
116 | 119 |
117 void CrossOperationDelegate::CopyOrMoveFile( | 120 void CrossOperationDelegate::CopyOrMoveFile(const Request& request) { |
118 const FileSystemURL& src, | |
119 const FileSystemURL& dest, | |
120 const StatusCallback& callback) { | |
121 // Same filesystem case. | 121 // Same filesystem case. |
122 if (same_file_system_) { | 122 if (same_file_system_) { |
123 if (operation_type_ == OPERATION_MOVE) | 123 if (operation_type_ == OPERATION_MOVE) { |
124 NewSourceOperation()->MoveFileLocal(src, dest, callback); | 124 NewSourceOperation()->MoveFileLocal(request.src, request.dest, |
125 else | 125 request.callback); |
126 NewSourceOperation()->CopyFileLocal(src, dest, callback); | 126 } else { |
| 127 NewSourceOperation()->CopyFileLocal(request.src, request.dest, |
| 128 request.callback); |
| 129 } |
127 return; | 130 return; |
128 } | 131 } |
129 | 132 |
130 // Cross filesystem case. | 133 // Cross filesystem case. |
131 // Perform CreateSnapshotFile, CopyInForeignFile and then calls | 134 // Perform CreateSnapshotFile, CopyInForeignFile and then calls |
132 // copy_callback which removes the source file if operation_type == MOVE. | 135 // copy_callback which removes the source file if operation_type == MOVE. |
133 StatusCallback copy_callback = | 136 StatusCallback copy_callback = |
134 base::Bind(&CrossOperationDelegate::DidFinishCopy, AsWeakPtr(), | 137 base::Bind(&CrossOperationDelegate::DidFinishCopy, AsWeakPtr(), request); |
135 src, callback); | 138 Request copy_request(request.src, request.dest, copy_callback); |
136 NewSourceOperation()->CreateSnapshotFile( | 139 NewSourceOperation()->CreateSnapshotFile( |
137 src, base::Bind(&CrossOperationDelegate::DidCreateSnapshot, AsWeakPtr(), | 140 request.src, |
138 dest, copy_callback)); | 141 base::Bind(&CrossOperationDelegate::DidCreateSnapshot, AsWeakPtr(), |
| 142 copy_request)); |
139 } | 143 } |
140 | 144 |
141 void CrossOperationDelegate::DidCreateSnapshot( | 145 void CrossOperationDelegate::DidCreateSnapshot( |
142 const FileSystemURL& dest, | 146 const Request& request, |
143 const StatusCallback& callback, | |
144 base::PlatformFileError error, | 147 base::PlatformFileError error, |
145 const base::PlatformFileInfo& file_info, | 148 const base::PlatformFileInfo& file_info, |
146 const base::FilePath& platform_path, | 149 const base::FilePath& platform_path, |
147 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | 150 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
148 if (error != base::PLATFORM_FILE_OK) { | 151 if (error != base::PLATFORM_FILE_OK) { |
149 callback.Run(error); | 152 request.callback.Run(error); |
150 return; | 153 return; |
151 } | 154 } |
152 current_file_ref_ = file_ref; | 155 current_file_ref_ = file_ref; |
153 | 156 |
154 // For now we assume CreateSnapshotFile always return a valid local file path. | 157 // For now we assume CreateSnapshotFile always return a valid local file path. |
155 // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. | 158 // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. |
156 DCHECK(!platform_path.empty()); | 159 DCHECK(!platform_path.empty()); |
157 | 160 |
158 CopyOrMoveFileValidatorFactory* factory = | 161 CopyOrMoveFileValidatorFactory* factory = |
159 file_system_context()->GetCopyOrMoveFileValidatorFactory( | 162 file_system_context()->GetCopyOrMoveFileValidatorFactory( |
160 dest_root_.type(), &error); | 163 dest_root_.type(), &error); |
161 if (error != base::PLATFORM_FILE_OK) { | 164 if (error != base::PLATFORM_FILE_OK) { |
162 callback.Run(error); | 165 request.callback.Run(error); |
163 return; | 166 return; |
164 } | 167 } |
165 if (!factory) { | 168 if (!factory) { |
166 DidValidateFile(dest, callback, file_info, platform_path, error); | 169 DidValidateFile(request, file_info, platform_path, error); |
167 return; | 170 return; |
168 } | 171 } |
169 | 172 |
170 validator_.reset(factory->CreateCopyOrMoveFileValidator(platform_path)); | 173 base::FilePath src_path = request.src.virtual_path(); |
| 174 validator_.reset( |
| 175 factory->CreateCopyOrMoveFileValidator(src_path, platform_path)); |
171 validator_->StartValidation( | 176 validator_->StartValidation( |
172 base::Bind(&CrossOperationDelegate::DidValidateFile, AsWeakPtr(), | 177 base::Bind(&CrossOperationDelegate::DidValidateFile, AsWeakPtr(), |
173 dest, callback, file_info, platform_path)); | 178 request, file_info, platform_path)); |
174 } | 179 } |
175 | 180 |
176 void CrossOperationDelegate::DidValidateFile( | 181 void CrossOperationDelegate::DidValidateFile( |
177 const FileSystemURL& dest, | 182 const Request& request, |
178 const StatusCallback& callback, | |
179 const base::PlatformFileInfo& file_info, | 183 const base::PlatformFileInfo& file_info, |
180 const base::FilePath& platform_path, | 184 const base::FilePath& platform_path, |
181 base::PlatformFileError error) { | 185 base::PlatformFileError error) { |
182 if (error != base::PLATFORM_FILE_OK) { | 186 if (error != base::PLATFORM_FILE_OK) { |
183 callback.Run(error); | 187 request.callback.Run(error); |
184 return; | 188 return; |
185 } | 189 } |
186 | 190 |
187 NewDestOperation()->CopyInForeignFile(platform_path, dest, callback); | 191 NewDestOperation()->CopyInForeignFile(platform_path, request.dest, |
| 192 request.callback); |
188 } | 193 } |
189 | 194 |
190 void CrossOperationDelegate::DidFinishCopy( | 195 void CrossOperationDelegate::DidFinishCopy( |
191 const FileSystemURL& src, | 196 const Request& request, |
192 const StatusCallback& callback, | |
193 base::PlatformFileError error) { | 197 base::PlatformFileError error) { |
194 if (error != base::PLATFORM_FILE_OK || | 198 if (error != base::PLATFORM_FILE_OK || |
195 operation_type_ == OPERATION_COPY) { | 199 operation_type_ == OPERATION_COPY) { |
196 callback.Run(error); | 200 request.callback.Run(error); |
197 return; | 201 return; |
198 } | 202 } |
199 | 203 |
200 DCHECK_EQ(OPERATION_MOVE, operation_type_); | 204 DCHECK_EQ(OPERATION_MOVE, operation_type_); |
201 | 205 |
202 // Remove the source for finalizing move operation. | 206 // Remove the source for finalizing move operation. |
203 NewSourceOperation()->Remove( | 207 NewSourceOperation()->Remove( |
204 src, true /* recursive */, | 208 request.src, true /* recursive */, |
205 base::Bind(&CrossOperationDelegate::DidRemoveSourceForMove, | 209 base::Bind(&CrossOperationDelegate::DidRemoveSourceForMove, |
206 AsWeakPtr(), callback)); | 210 AsWeakPtr(), request)); |
207 } | 211 } |
208 | 212 |
209 void CrossOperationDelegate::DidRemoveSourceForMove( | 213 void CrossOperationDelegate::DidRemoveSourceForMove( |
210 const StatusCallback& callback, | 214 const Request& request, |
211 base::PlatformFileError error) { | 215 base::PlatformFileError error) { |
212 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 216 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
213 error = base::PLATFORM_FILE_OK; | 217 error = base::PLATFORM_FILE_OK; |
214 callback.Run(error); | 218 request.callback.Run(error); |
215 } | 219 } |
216 | 220 |
217 FileSystemURL CrossOperationDelegate::CreateDestURL( | 221 FileSystemURL CrossOperationDelegate::CreateDestURL( |
218 const FileSystemURL& src_url) const { | 222 const FileSystemURL& src_url) const { |
219 DCHECK_EQ(src_root_.type(), src_url.type()); | 223 DCHECK_EQ(src_root_.type(), src_url.type()); |
220 DCHECK_EQ(src_root_.origin(), src_url.origin()); | 224 DCHECK_EQ(src_root_.origin(), src_url.origin()); |
221 | 225 |
222 base::FilePath relative = dest_root_.virtual_path(); | 226 base::FilePath relative = dest_root_.virtual_path(); |
223 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), | 227 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), |
224 &relative); | 228 &relative); |
225 return file_system_context()->CreateCrackedFileSystemURL( | 229 return file_system_context()->CreateCrackedFileSystemURL( |
226 dest_root_.origin(), | 230 dest_root_.origin(), |
227 dest_root_.mount_type(), | 231 dest_root_.mount_type(), |
228 relative); | 232 relative); |
229 } | 233 } |
230 | 234 |
231 LocalFileSystemOperation* CrossOperationDelegate::NewDestOperation() { | 235 LocalFileSystemOperation* CrossOperationDelegate::NewDestOperation() { |
232 return NewNestedOperation(); | 236 return NewNestedOperation(); |
233 } | 237 } |
234 | 238 |
235 LocalFileSystemOperation* CrossOperationDelegate::NewSourceOperation() { | 239 LocalFileSystemOperation* CrossOperationDelegate::NewSourceOperation() { |
236 if (same_file_system_) | 240 if (same_file_system_) |
237 return NewDestOperation(); | 241 return NewDestOperation(); |
238 return src_root_operation_->CreateNestedOperation(); | 242 return src_root_operation_->CreateNestedOperation(); |
239 } | 243 } |
240 | 244 |
241 } // namespace fileapi | 245 } // namespace fileapi |
OLD | NEW |