Chromium Code Reviews| 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 |