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