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/browser/fileapi/copy_or_move_operation_delegate.h" | 5 #include "webkit/browser/fileapi/copy_or_move_operation_delegate.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" | 9 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" |
10 #include "webkit/browser/fileapi/file_system_context.h" | 10 #include "webkit/browser/fileapi/file_system_context.h" |
11 #include "webkit/browser/fileapi/file_system_operation_runner.h" | 11 #include "webkit/browser/fileapi/file_system_operation_runner.h" |
12 #include "webkit/browser/fileapi/file_system_url.h" | 12 #include "webkit/browser/fileapi/file_system_url.h" |
13 #include "webkit/browser/fileapi/recursive_operation_delegate.h" | 13 #include "webkit/browser/fileapi/recursive_operation_delegate.h" |
14 #include "webkit/common/blob/shareable_file_reference.h" | 14 #include "webkit/common/blob/shareable_file_reference.h" |
15 #include "webkit/common/fileapi/file_system_util.h" | 15 #include "webkit/common/fileapi/file_system_util.h" |
16 | 16 |
17 namespace fileapi { | 17 namespace fileapi { |
18 | 18 |
| 19 class CopyOrMoveOperationDelegate::CopyOrMoveImpl { |
| 20 public: |
| 21 virtual ~CopyOrMoveImpl() {} |
| 22 virtual void Run( |
| 23 const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0; |
| 24 protected: |
| 25 CopyOrMoveImpl() {} |
| 26 DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl); |
| 27 }; |
| 28 |
| 29 namespace { |
| 30 |
| 31 // Copies a file on a (same) file system. Just delegate the operation to |
| 32 // |operation_runner|. |
| 33 class CopyOrMoveOnSameFileSystemImpl |
| 34 : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { |
| 35 public: |
| 36 CopyOrMoveOnSameFileSystemImpl( |
| 37 FileSystemOperationRunner* operation_runner, |
| 38 CopyOrMoveOperationDelegate::OperationType operation_type, |
| 39 const FileSystemURL& src_url, |
| 40 const FileSystemURL& dest_url) |
| 41 : operation_runner_(operation_runner), |
| 42 operation_type_(operation_type), |
| 43 src_url_(src_url), |
| 44 dest_url_(dest_url) { |
| 45 } |
| 46 |
| 47 virtual void Run( |
| 48 const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { |
| 49 if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) { |
| 50 operation_runner_->MoveFileLocal(src_url_, dest_url_, callback); |
| 51 } else { |
| 52 // TODO(hidehiko): Support progress callback. |
| 53 operation_runner_->CopyFileLocal( |
| 54 src_url_, dest_url_, |
| 55 FileSystemOperationRunner::CopyFileProgressCallback(), callback); |
| 56 } |
| 57 } |
| 58 |
| 59 private: |
| 60 FileSystemOperationRunner* operation_runner_; |
| 61 CopyOrMoveOperationDelegate::OperationType operation_type_; |
| 62 FileSystemURL src_url_; |
| 63 FileSystemURL dest_url_; |
| 64 DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl); |
| 65 }; |
| 66 |
| 67 // Specifically for cross file system copy/move operation, this class creates |
| 68 // a snapshot file, validates it if necessary, runs copying process, |
| 69 // validates the created file, and removes source file for move (noop for |
| 70 // copy). |
| 71 class SnapshotCopyOrMoveImpl |
| 72 : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { |
| 73 public: |
| 74 SnapshotCopyOrMoveImpl( |
| 75 FileSystemOperationRunner* operation_runner, |
| 76 CopyOrMoveOperationDelegate::OperationType operation_type, |
| 77 const FileSystemURL& src_url, |
| 78 const FileSystemURL& dest_url, |
| 79 CopyOrMoveFileValidatorFactory* validator_factory) |
| 80 : operation_runner_(operation_runner), |
| 81 operation_type_(operation_type), |
| 82 src_url_(src_url), |
| 83 dest_url_(dest_url), |
| 84 validator_factory_(validator_factory), |
| 85 weak_factory_(this) { |
| 86 } |
| 87 |
| 88 virtual void Run( |
| 89 const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { |
| 90 operation_runner_->CreateSnapshotFile( |
| 91 src_url_, |
| 92 base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot, |
| 93 weak_factory_.GetWeakPtr(), callback)); |
| 94 } |
| 95 |
| 96 private: |
| 97 void RunAfterCreateSnapshot( |
| 98 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 99 base::PlatformFileError error, |
| 100 const base::PlatformFileInfo& file_info, |
| 101 const base::FilePath& platform_path, |
| 102 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
| 103 if (error != base::PLATFORM_FILE_OK) { |
| 104 callback.Run(error); |
| 105 return; |
| 106 } |
| 107 |
| 108 // For now we assume CreateSnapshotFile always return a valid local file |
| 109 // path. |
| 110 DCHECK(!platform_path.empty()); |
| 111 |
| 112 if (!validator_factory_) { |
| 113 // No validation is needed. |
| 114 RunAfterPreWriteValidation( |
| 115 platform_path, file_ref, callback, base::PLATFORM_FILE_OK); |
| 116 return; |
| 117 } |
| 118 |
| 119 // Run pre write validation. |
| 120 PreWriteValidation( |
| 121 platform_path, |
| 122 base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation, |
| 123 weak_factory_.GetWeakPtr(), |
| 124 platform_path, file_ref, callback)); |
| 125 } |
| 126 |
| 127 void RunAfterPreWriteValidation( |
| 128 const base::FilePath& platform_path, |
| 129 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, |
| 130 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 131 base::PlatformFileError error) { |
| 132 if (error != base::PLATFORM_FILE_OK) { |
| 133 callback.Run(error); |
| 134 return; |
| 135 } |
| 136 |
| 137 // |file_ref| is unused but necessary to keep the file alive until |
| 138 // CopyInForeignFile() is completed. |
| 139 operation_runner_->CopyInForeignFile( |
| 140 platform_path, dest_url_, |
| 141 base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile, |
| 142 weak_factory_.GetWeakPtr(), file_ref, callback)); |
| 143 } |
| 144 |
| 145 void RunAfterCopyInForeignFile( |
| 146 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, |
| 147 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 148 base::PlatformFileError error) { |
| 149 if (error != base::PLATFORM_FILE_OK) { |
| 150 callback.Run(error); |
| 151 return; |
| 152 } |
| 153 |
| 154 // |validator_| is NULL when the destination filesystem does not do |
| 155 // validation. |
| 156 if (!validator_) { |
| 157 // No validation is needed. |
| 158 RunAfterPostWriteValidation(callback, base::PLATFORM_FILE_OK); |
| 159 return; |
| 160 } |
| 161 |
| 162 PostWriteValidation( |
| 163 base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation, |
| 164 weak_factory_.GetWeakPtr(), callback)); |
| 165 } |
| 166 |
| 167 void RunAfterPostWriteValidation( |
| 168 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 169 base::PlatformFileError error) { |
| 170 if (error != base::PLATFORM_FILE_OK) { |
| 171 // Failed to validate. Remove the destination file. |
| 172 operation_runner_->Remove( |
| 173 dest_url_, true /* recursive */, |
| 174 base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError, |
| 175 weak_factory_.GetWeakPtr(), error, callback)); |
| 176 return; |
| 177 } |
| 178 |
| 179 if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) { |
| 180 callback.Run(base::PLATFORM_FILE_OK); |
| 181 return; |
| 182 } |
| 183 |
| 184 DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_); |
| 185 |
| 186 // Remove the source for finalizing move operation. |
| 187 operation_runner_->Remove( |
| 188 src_url_, true /* recursive */, |
| 189 base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove, |
| 190 weak_factory_.GetWeakPtr(), callback)); |
| 191 } |
| 192 |
| 193 void RunAfterRemoveSourceForMove( |
| 194 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 195 base::PlatformFileError error) { |
| 196 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
| 197 error = base::PLATFORM_FILE_OK; |
| 198 callback.Run(error); |
| 199 } |
| 200 |
| 201 void DidRemoveDestForError( |
| 202 base::PlatformFileError prior_error, |
| 203 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 204 base::PlatformFileError error) { |
| 205 if (error != base::PLATFORM_FILE_OK) { |
| 206 VLOG(1) << "Error removing destination file after validation error: " |
| 207 << error; |
| 208 } |
| 209 callback.Run(prior_error); |
| 210 } |
| 211 |
| 212 // Runs pre-write validation. |
| 213 void PreWriteValidation( |
| 214 const base::FilePath& platform_path, |
| 215 const CopyOrMoveOperationDelegate::StatusCallback& callback) { |
| 216 DCHECK(validator_factory_); |
| 217 validator_.reset( |
| 218 validator_factory_->CreateCopyOrMoveFileValidator( |
| 219 src_url_, platform_path)); |
| 220 validator_->StartPreWriteValidation(callback); |
| 221 } |
| 222 |
| 223 // Runs post-write validation. |
| 224 void PostWriteValidation( |
| 225 const CopyOrMoveOperationDelegate::StatusCallback& callback) { |
| 226 operation_runner_->CreateSnapshotFile( |
| 227 dest_url_, |
| 228 base::Bind( |
| 229 &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile, |
| 230 weak_factory_.GetWeakPtr(), callback)); |
| 231 } |
| 232 |
| 233 void PostWriteValidationAfterCreateSnapshotFile( |
| 234 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 235 base::PlatformFileError error, |
| 236 const base::PlatformFileInfo& file_info, |
| 237 const base::FilePath& platform_path, |
| 238 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
| 239 if (error != base::PLATFORM_FILE_OK) { |
| 240 callback.Run(error); |
| 241 return; |
| 242 } |
| 243 |
| 244 DCHECK(validator_); |
| 245 // Note: file_ref passed here to keep the file alive until after |
| 246 // the StartPostWriteValidation operation finishes. |
| 247 validator_->StartPostWriteValidation( |
| 248 platform_path, |
| 249 base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation, |
| 250 weak_factory_.GetWeakPtr(), file_ref, callback)); |
| 251 } |
| 252 |
| 253 // |file_ref| is unused; it is passed here to make sure the reference is |
| 254 // alive until after post-write validation is complete. |
| 255 void DidPostWriteValidation( |
| 256 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, |
| 257 const CopyOrMoveOperationDelegate::StatusCallback& callback, |
| 258 base::PlatformFileError error) { |
| 259 callback.Run(error); |
| 260 } |
| 261 |
| 262 FileSystemOperationRunner* operation_runner_; |
| 263 CopyOrMoveOperationDelegate::OperationType operation_type_; |
| 264 FileSystemURL src_url_; |
| 265 FileSystemURL dest_url_; |
| 266 CopyOrMoveFileValidatorFactory* validator_factory_; |
| 267 scoped_ptr<CopyOrMoveFileValidator> validator_; |
| 268 |
| 269 base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_; |
| 270 DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl); |
| 271 }; |
| 272 |
| 273 } // namespace |
| 274 |
| 275 |
19 CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( | 276 CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( |
20 FileSystemContext* file_system_context, | 277 FileSystemContext* file_system_context, |
21 const FileSystemURL& src_root, | 278 const FileSystemURL& src_root, |
22 const FileSystemURL& dest_root, | 279 const FileSystemURL& dest_root, |
23 OperationType operation_type, | 280 OperationType operation_type, |
24 const StatusCallback& callback) | 281 const StatusCallback& callback) |
25 : RecursiveOperationDelegate(file_system_context), | 282 : RecursiveOperationDelegate(file_system_context), |
26 src_root_(src_root), | 283 src_root_(src_root), |
27 dest_root_(dest_root), | 284 dest_root_(dest_root), |
28 operation_type_(operation_type), | 285 operation_type_(operation_type), |
29 callback_(callback), | 286 callback_(callback), |
30 weak_factory_(this) { | 287 weak_factory_(this) { |
31 same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); | 288 same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); |
32 } | 289 } |
33 | 290 |
34 CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() { | 291 CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() { |
| 292 STLDeleteElements(&running_copy_set_); |
35 } | 293 } |
36 | 294 |
37 void CopyOrMoveOperationDelegate::Run() { | 295 void CopyOrMoveOperationDelegate::Run() { |
38 // Not supported; this should never be called. | 296 // Not supported; this should never be called. |
39 NOTREACHED(); | 297 NOTREACHED(); |
40 } | 298 } |
41 | 299 |
42 void CopyOrMoveOperationDelegate::RunRecursively() { | 300 void CopyOrMoveOperationDelegate::RunRecursively() { |
43 // Perform light-weight checks first. | 301 // Perform light-weight checks first. |
44 | 302 |
45 // It is an error to try to copy/move an entry into its child. | 303 // It is an error to try to copy/move an entry into its child. |
46 if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) { | 304 if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) { |
47 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 305 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); |
48 return; | 306 return; |
49 } | 307 } |
50 | 308 |
51 // It is an error to copy/move an entry into the same path. | 309 // It is an error to copy/move an entry into the same path. |
52 if (same_file_system_ && src_root_.path() == dest_root_.path()) { | 310 if (same_file_system_ && src_root_.path() == dest_root_.path()) { |
53 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); | 311 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); |
54 return; | 312 return; |
55 } | 313 } |
56 | 314 |
57 // First try to copy/move it as a file. | 315 // First try to copy/move it as a file. |
58 CopyOrMoveFile(URLPair(src_root_, dest_root_), | 316 CopyOrMoveFile(src_root_, dest_root_, |
59 base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile, | 317 base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile, |
60 weak_factory_.GetWeakPtr())); | 318 weak_factory_.GetWeakPtr())); |
61 } | 319 } |
62 | 320 |
63 void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url, | 321 void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url, |
64 const StatusCallback& callback) { | 322 const StatusCallback& callback) { |
65 CopyOrMoveFile(URLPair(src_url, CreateDestURL(src_url)), callback); | 323 CopyOrMoveFile(src_url, CreateDestURL(src_url), callback); |
66 } | 324 } |
67 | 325 |
68 void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, | 326 void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, |
69 const StatusCallback& callback) { | 327 const StatusCallback& callback) { |
70 FileSystemURL dest_url = CreateDestURL(src_url); | 328 FileSystemURL dest_url = CreateDestURL(src_url); |
71 | 329 |
72 // If operation_type == Move we may need to record directories and | 330 // If operation_type == Move we may need to record directories and |
73 // restore directory timestamps in the end, though it may have | 331 // restore directory timestamps in the end, though it may have |
74 // negative performance impact. | 332 // negative performance impact. |
75 // See http://crbug.com/171284 for more details. | 333 // See http://crbug.com/171284 for more details. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 // Start to process the source directory recursively. | 367 // Start to process the source directory recursively. |
110 // TODO(kinuko): This could be too expensive for same_file_system_==true | 368 // TODO(kinuko): This could be too expensive for same_file_system_==true |
111 // and operation==MOVE case, probably we can just rename the root directory. | 369 // and operation==MOVE case, probably we can just rename the root directory. |
112 // http://crbug.com/172187 | 370 // http://crbug.com/172187 |
113 StartRecursiveOperation( | 371 StartRecursiveOperation( |
114 src_root_, | 372 src_root_, |
115 base::Bind(&CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir, | 373 base::Bind(&CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir, |
116 weak_factory_.GetWeakPtr(), src_root_, callback_)); | 374 weak_factory_.GetWeakPtr(), src_root_, callback_)); |
117 } | 375 } |
118 | 376 |
119 void CopyOrMoveOperationDelegate::CopyOrMoveFile( | |
120 const URLPair& url_pair, | |
121 const StatusCallback& callback) { | |
122 // Same filesystem case. | |
123 if (same_file_system_) { | |
124 if (operation_type_ == OPERATION_MOVE) { | |
125 operation_runner()->MoveFileLocal(url_pair.src, url_pair.dest, callback); | |
126 } else { | |
127 // TODO(hidehiko): Support progress callback. | |
128 operation_runner()->CopyFileLocal( | |
129 url_pair.src, url_pair.dest, | |
130 FileSystemOperationRunner::CopyFileProgressCallback(), callback); | |
131 } | |
132 return; | |
133 } | |
134 | |
135 // Cross filesystem case. | |
136 // Perform CreateSnapshotFile, CopyInForeignFile and then calls | |
137 // copy_callback which removes the source file if operation_type == MOVE. | |
138 StatusCallback copy_callback = | |
139 base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, | |
140 weak_factory_.GetWeakPtr(), url_pair, callback); | |
141 operation_runner()->CreateSnapshotFile( | |
142 url_pair.src, | |
143 base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot, | |
144 weak_factory_.GetWeakPtr(), url_pair, copy_callback)); | |
145 } | |
146 | |
147 void CopyOrMoveOperationDelegate::DidCreateSnapshot( | |
148 const URLPair& url_pair, | |
149 const StatusCallback& callback, | |
150 base::PlatformFileError error, | |
151 const base::PlatformFileInfo& file_info, | |
152 const base::FilePath& platform_path, | |
153 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | |
154 if (error != base::PLATFORM_FILE_OK) { | |
155 callback.Run(error); | |
156 return; | |
157 } | |
158 current_file_ref_ = file_ref; | |
159 | |
160 // For now we assume CreateSnapshotFile always return a valid local file path. | |
161 // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. | |
162 DCHECK(!platform_path.empty()); | |
163 | |
164 CopyOrMoveFileValidatorFactory* factory = | |
165 file_system_context()->GetCopyOrMoveFileValidatorFactory( | |
166 dest_root_.type(), &error); | |
167 if (error != base::PLATFORM_FILE_OK) { | |
168 callback.Run(error); | |
169 return; | |
170 } | |
171 if (!factory) { | |
172 DidValidateFile(url_pair.dest, callback, file_info, platform_path, error); | |
173 return; | |
174 } | |
175 | |
176 validator_.reset( | |
177 factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path)); | |
178 validator_->StartPreWriteValidation( | |
179 base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile, | |
180 weak_factory_.GetWeakPtr(), | |
181 url_pair.dest, callback, file_info, platform_path)); | |
182 } | |
183 | |
184 void CopyOrMoveOperationDelegate::DidValidateFile( | |
185 const FileSystemURL& dest, | |
186 const StatusCallback& callback, | |
187 const base::PlatformFileInfo& file_info, | |
188 const base::FilePath& platform_path, | |
189 base::PlatformFileError error) { | |
190 if (error != base::PLATFORM_FILE_OK) { | |
191 callback.Run(error); | |
192 return; | |
193 } | |
194 | |
195 operation_runner()->CopyInForeignFile(platform_path, dest, callback); | |
196 } | |
197 | |
198 void CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir( | 377 void CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir( |
199 const FileSystemURL& src, | 378 const FileSystemURL& src, |
200 const StatusCallback& callback, | 379 const StatusCallback& callback, |
201 base::PlatformFileError error) { | 380 base::PlatformFileError error) { |
202 if (error != base::PLATFORM_FILE_OK || | 381 if (error != base::PLATFORM_FILE_OK || |
203 operation_type_ == OPERATION_COPY) { | 382 operation_type_ == OPERATION_COPY) { |
204 callback.Run(error); | 383 callback.Run(error); |
205 return; | 384 return; |
206 } | 385 } |
207 | 386 |
208 DCHECK_EQ(OPERATION_MOVE, operation_type_); | 387 DCHECK_EQ(OPERATION_MOVE, operation_type_); |
209 | 388 |
210 // Remove the source for finalizing move operation. | 389 // Remove the source for finalizing move operation. |
211 operation_runner()->Remove( | 390 operation_runner()->Remove( |
212 src, true /* recursive */, | 391 src, true /* recursive */, |
213 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, | 392 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, |
214 weak_factory_.GetWeakPtr(), callback)); | 393 weak_factory_.GetWeakPtr(), callback)); |
215 } | 394 } |
216 | 395 |
217 void CopyOrMoveOperationDelegate::DidFinishCopy( | |
218 const URLPair& url_pair, | |
219 const StatusCallback& callback, | |
220 base::PlatformFileError error) { | |
221 if (error != base::PLATFORM_FILE_OK) { | |
222 callback.Run(error); | |
223 return; | |
224 } | |
225 | |
226 // |validator_| is NULL in the same-filesystem case or when the destination | |
227 // filesystem does not do validation. | |
228 if (!validator_.get()) { | |
229 scoped_refptr<webkit_blob::ShareableFileReference> file_ref; | |
230 DidPostWriteValidation(url_pair, callback, file_ref, | |
231 base::PLATFORM_FILE_OK); | |
232 return; | |
233 } | |
234 | |
235 DCHECK(!same_file_system_); | |
236 operation_runner()->CreateSnapshotFile( | |
237 url_pair.dest, | |
238 base::Bind(&CopyOrMoveOperationDelegate::DoPostWriteValidation, | |
239 weak_factory_.GetWeakPtr(), url_pair, callback)); | |
240 } | |
241 | |
242 void CopyOrMoveOperationDelegate::DoPostWriteValidation( | |
243 const URLPair& url_pair, | |
244 const StatusCallback& callback, | |
245 base::PlatformFileError error, | |
246 const base::PlatformFileInfo& file_info, | |
247 const base::FilePath& platform_path, | |
248 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | |
249 if (error != base::PLATFORM_FILE_OK) { | |
250 operation_runner()->Remove( | |
251 url_pair.dest, true, | |
252 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError, | |
253 weak_factory_.GetWeakPtr(), error, callback)); | |
254 return; | |
255 } | |
256 | |
257 DCHECK(validator_.get()); | |
258 // Note: file_ref passed here to keep the file alive until after | |
259 // the StartPostWriteValidation operation finishes. | |
260 validator_->StartPostWriteValidation( | |
261 platform_path, | |
262 base::Bind(&CopyOrMoveOperationDelegate::DidPostWriteValidation, | |
263 weak_factory_.GetWeakPtr(), url_pair, callback, file_ref)); | |
264 } | |
265 | |
266 // |file_ref| is unused; it is passed here to make sure the reference is | |
267 // alive until after post-write validation is complete. | |
268 void CopyOrMoveOperationDelegate::DidPostWriteValidation( | |
269 const URLPair& url_pair, | |
270 const StatusCallback& callback, | |
271 const scoped_refptr<webkit_blob::ShareableFileReference>& /*file_ref*/, | |
272 base::PlatformFileError error) { | |
273 if (error != base::PLATFORM_FILE_OK) { | |
274 operation_runner()->Remove( | |
275 url_pair.dest, true, | |
276 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError, | |
277 weak_factory_.GetWeakPtr(), error, callback)); | |
278 return; | |
279 } | |
280 | |
281 if (operation_type_ == OPERATION_COPY) { | |
282 callback.Run(error); | |
283 return; | |
284 } | |
285 | |
286 DCHECK_EQ(OPERATION_MOVE, operation_type_); | |
287 | |
288 // Remove the source for finalizing move operation. | |
289 operation_runner()->Remove( | |
290 url_pair.src, true /* recursive */, | |
291 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, | |
292 weak_factory_.GetWeakPtr(), callback)); | |
293 } | |
294 | |
295 void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( | 396 void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( |
296 const StatusCallback& callback, | 397 const StatusCallback& callback, |
297 base::PlatformFileError error) { | 398 base::PlatformFileError error) { |
298 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 399 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
299 error = base::PLATFORM_FILE_OK; | 400 error = base::PLATFORM_FILE_OK; |
300 callback.Run(error); | 401 callback.Run(error); |
301 } | 402 } |
302 | 403 |
| 404 void CopyOrMoveOperationDelegate::CopyOrMoveFile( |
| 405 const FileSystemURL& src_url, |
| 406 const FileSystemURL& dest_url, |
| 407 const StatusCallback& callback) { |
| 408 CopyOrMoveImpl* impl = NULL; |
| 409 if (same_file_system_) { |
| 410 impl = new CopyOrMoveOnSameFileSystemImpl( |
| 411 operation_runner(), operation_type_, src_url, dest_url); |
| 412 } else { |
| 413 // Cross filesystem case. |
| 414 // TODO(hidehiko): Support stream based copy. crbug.com/279287. |
| 415 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; |
| 416 CopyOrMoveFileValidatorFactory* validator_factory = |
| 417 file_system_context()->GetCopyOrMoveFileValidatorFactory( |
| 418 dest_root_.type(), &error); |
| 419 if (error != base::PLATFORM_FILE_OK) { |
| 420 callback.Run(error); |
| 421 return; |
| 422 } |
| 423 |
| 424 impl = new SnapshotCopyOrMoveImpl( |
| 425 operation_runner(), operation_type_, src_url, dest_url, |
| 426 validator_factory); |
| 427 } |
| 428 |
| 429 // Register the running task. |
| 430 running_copy_set_.insert(impl); |
| 431 impl->Run(base::Bind(&CopyOrMoveOperationDelegate::DidCopyOrMoveFile, |
| 432 weak_factory_.GetWeakPtr(), impl, callback)); |
| 433 } |
| 434 |
| 435 void CopyOrMoveOperationDelegate::DidCopyOrMoveFile( |
| 436 CopyOrMoveImpl* impl, |
| 437 const StatusCallback& callback, |
| 438 base::PlatformFileError error) { |
| 439 running_copy_set_.erase(impl); |
| 440 delete impl; |
| 441 callback.Run(error); |
| 442 } |
| 443 |
303 FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( | 444 FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( |
304 const FileSystemURL& src_url) const { | 445 const FileSystemURL& src_url) const { |
305 DCHECK_EQ(src_root_.type(), src_url.type()); | 446 DCHECK_EQ(src_root_.type(), src_url.type()); |
306 DCHECK_EQ(src_root_.origin(), src_url.origin()); | 447 DCHECK_EQ(src_root_.origin(), src_url.origin()); |
307 | 448 |
308 base::FilePath relative = dest_root_.virtual_path(); | 449 base::FilePath relative = dest_root_.virtual_path(); |
309 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), | 450 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), |
310 &relative); | 451 &relative); |
311 return file_system_context()->CreateCrackedFileSystemURL( | 452 return file_system_context()->CreateCrackedFileSystemURL( |
312 dest_root_.origin(), | 453 dest_root_.origin(), |
313 dest_root_.mount_type(), | 454 dest_root_.mount_type(), |
314 relative); | 455 relative); |
315 } | 456 } |
316 | 457 |
317 void CopyOrMoveOperationDelegate::DidRemoveDestForError( | |
318 base::PlatformFileError prior_error, | |
319 const StatusCallback& callback, | |
320 base::PlatformFileError error) { | |
321 if (error != base::PLATFORM_FILE_OK) { | |
322 VLOG(1) << "Error removing destination file after validation error: " | |
323 << error; | |
324 } | |
325 callback.Run(prior_error); | |
326 } | |
327 | |
328 } // namespace fileapi | 458 } // namespace fileapi |
OLD | NEW |