Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/file_util_helper.h" | 5 #include "webkit/fileapi/file_util_helper.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "webkit/fileapi/file_system_file_util.h" | 10 #include "webkit/fileapi/file_system_file_util.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 DCHECK(src_util_); | 103 DCHECK(src_util_); |
| 104 DCHECK(dest_util_); | 104 DCHECK(dest_util_); |
| 105 same_file_system_ = | 105 same_file_system_ = |
| 106 src_root_url_.origin() == dest_root_url_.origin() && | 106 src_root_url_.origin() == dest_root_url_.origin() && |
| 107 src_root_url_.type() == dest_root_url_.type(); | 107 src_root_url_.type() == dest_root_url_.type(); |
| 108 } | 108 } |
| 109 | 109 |
| 110 CrossFileUtilHelper::~CrossFileUtilHelper() {} | 110 CrossFileUtilHelper::~CrossFileUtilHelper() {} |
| 111 | 111 |
| 112 base::PlatformFileError CrossFileUtilHelper::DoWork() { | 112 base::PlatformFileError CrossFileUtilHelper::DoWork() { |
| 113 base::PlatformFileError error = PerformErrorCheckAndPreparation(); | |
| 114 if (error != base::PLATFORM_FILE_OK) | |
| 115 return error; | |
| 116 if (FileUtilHelper::DirectoryExists(context_, src_util_, src_root_url_)) | |
| 117 return CopyOrMoveDirectory(src_root_url_, dest_root_url_); | |
| 118 return CopyOrMoveFile(src_root_url_, dest_root_url_); | |
| 119 } | |
| 120 | |
| 121 PlatformFileError CrossFileUtilHelper::PerformErrorCheckAndPreparation() { | |
| 122 FilePath platform_path; | |
| 123 base::PlatformFileInfo src_root_info; | |
| 124 base::PlatformFileInfo dest_root_info; | |
| 125 | |
| 126 PlatformFileError error = src_util_->GetFileInfo( | |
| 127 context_, src_root_url_, &src_root_info, &platform_path); | |
| 128 | |
| 129 if (error != base::PLATFORM_FILE_OK) | |
| 130 return error; | |
| 131 | |
| 132 error = dest_util_->GetFileInfo( | |
| 133 context_, dest_root_url_, &dest_root_info, &platform_path); | |
| 134 bool dest_root_exists = (error == base::PLATFORM_FILE_OK); | |
| 135 bool dest_parent_exists = dest_root_exists || IsInRoot(dest_root_url_); | |
| 136 | |
| 137 if (!dest_parent_exists) { | |
| 138 base::PlatformFileInfo file_info; | |
| 139 FileSystemURL parent_url = dest_root_url_.WithPath( | |
| 140 dest_root_url_.path().DirName()); | |
| 141 error = dest_util_->GetFileInfo( | |
| 142 context_, parent_url, &file_info, &platform_path); | |
| 143 dest_parent_exists = (error == base::PLATFORM_FILE_OK && | |
| 144 file_info.is_directory); | |
| 145 } | |
| 146 | |
| 147 // The parent of the |dest_root_url_| does not exist. | |
| 148 if (!dest_parent_exists) | |
| 149 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 150 | |
| 151 // It is an error to try to copy/move an entry into its child. | 113 // It is an error to try to copy/move an entry into its child. |
| 152 if (same_file_system_ && src_root_url_.path().IsParent(dest_root_url_.path())) | 114 if (same_file_system_ && src_root_url_.path().IsParent(dest_root_url_.path())) |
| 153 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 115 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 154 | 116 |
| 155 // Now it is ok to return if the |dest_root_url_| does not exist. | |
| 156 if (!dest_root_exists) | |
| 157 return base::PLATFORM_FILE_OK; | |
| 158 | |
| 159 // |src_root_url_| exists and is a directory. | |
| 160 // |dest_root_url_| exists and is a file. | |
| 161 bool src_is_directory = src_root_info.is_directory; | |
| 162 bool dest_is_directory = dest_root_info.is_directory; | |
| 163 | |
| 164 // Either one of |src_root_url_| or |dest_root_url_| is directory, | |
| 165 // while the other is not. | |
| 166 if (src_is_directory != dest_is_directory) | |
| 167 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
| 168 | |
| 169 // It is an error to copy/move an entry into the same path. | 117 // It is an error to copy/move an entry into the same path. |
| 170 if (same_file_system_ && | 118 if (same_file_system_ && |
| 171 src_root_url_.path() == dest_root_url_.path()) | 119 src_root_url_.path() == dest_root_url_.path()) |
| 172 return base::PLATFORM_FILE_ERROR_EXISTS; | 120 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 173 | 121 |
| 174 if (dest_is_directory) { | 122 // First try to copy/move the file. |
| 175 // It is an error to copy/move an entry to a non-empty directory. | 123 base::PlatformFileError error = CopyOrMoveFile(src_root_url_, dest_root_url_); |
| 176 // Otherwise the copy/move attempt must overwrite the destination, but | 124 if (error == base::PLATFORM_FILE_OK || |
| 177 // the file_util's Copy or Move method doesn't perform overwrite | 125 (error != base::PLATFORM_FILE_OK && |
|
tzik
2013/01/21 07:10:41
can we drop this?
kinuko
2013/01/21 07:57:55
Done.
| |
| 178 // on all platforms, so we delete the destination directory here. | 126 error != base::PLATFORM_FILE_ERROR_NOT_A_FILE)) |
| 179 if (base::PLATFORM_FILE_OK != | 127 return error; |
| 180 dest_util_->DeleteSingleDirectory(context_, dest_root_url_)) { | 128 |
| 181 if (!dest_util_->IsDirectoryEmpty(context_, dest_root_url_)) | 129 // Now we should be sure that the source (and destination if exists) |
| 182 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 130 // is directory. |
| 183 return base::PLATFORM_FILE_ERROR_FAILED; | 131 // Now let's try to remove the destination directory, this must |
| 184 } | 132 // fail if the directory isn't empty or its parent doesn't exist. |
| 185 } | 133 error = dest_util_->DeleteDirectory(context_, dest_root_url_); |
| 186 return base::PLATFORM_FILE_OK; | 134 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) |
| 135 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
| 136 if (error != base::PLATFORM_FILE_OK && | |
| 137 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) | |
| 138 return error; | |
| 139 | |
| 140 // Perform the actual work for directory copy/move. | |
| 141 return CopyOrMoveDirectory(src_root_url_, dest_root_url_); | |
| 187 } | 142 } |
| 188 | 143 |
| 189 PlatformFileError CrossFileUtilHelper::CopyOrMoveDirectory( | 144 PlatformFileError CrossFileUtilHelper::CopyOrMoveDirectory( |
| 190 const FileSystemURL& src_url, | 145 const FileSystemURL& src_url, |
| 191 const FileSystemURL& dest_url) { | 146 const FileSystemURL& dest_url) { |
| 192 // At this point we must have gone through | 147 // At this point we must have gone through |
| 193 // PerformErrorCheckAndPreparationForMoveAndCopy so this must be true. | 148 // PerformErrorCheckAndPreparationForMoveAndCopy so this must be true. |
| 194 DCHECK(!same_file_system_ || | 149 DCHECK(!same_file_system_ || |
| 195 !src_url.path().IsParent(dest_url.path())); | 150 !src_url.path().IsParent(dest_url.path())); |
| 196 | 151 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 base::PlatformFileInfo file_info; | 232 base::PlatformFileInfo file_info; |
| 278 FilePath platform_file_path; | 233 FilePath platform_file_path; |
| 279 FileSystemFileUtil::SnapshotFilePolicy snapshot_policy; | 234 FileSystemFileUtil::SnapshotFilePolicy snapshot_policy; |
| 280 | 235 |
| 281 PlatformFileError error = src_util_->CreateSnapshotFile( | 236 PlatformFileError error = src_util_->CreateSnapshotFile( |
| 282 context_, src_url, &file_info, &platform_file_path, &snapshot_policy); | 237 context_, src_url, &file_info, &platform_file_path, &snapshot_policy); |
| 283 if (error != base::PLATFORM_FILE_OK) | 238 if (error != base::PLATFORM_FILE_OK) |
| 284 return error; | 239 return error; |
| 285 | 240 |
| 286 // For now we don't support non-snapshot file case. | 241 // For now we don't support non-snapshot file case. |
| 242 // TODO(kinuko): Address this case too. | |
| 287 DCHECK(!platform_file_path.empty()); | 243 DCHECK(!platform_file_path.empty()); |
| 288 | 244 |
| 289 scoped_ptr<ScopedFileDeleter> file_deleter; | 245 scoped_ptr<ScopedFileDeleter> file_deleter; |
| 290 if (snapshot_policy == FileSystemFileUtil::kSnapshotFileTemporary) | 246 if (snapshot_policy == FileSystemFileUtil::kSnapshotFileTemporary) |
| 291 file_deleter.reset(new ScopedFileDeleter(platform_file_path)); | 247 file_deleter.reset(new ScopedFileDeleter(platform_file_path)); |
| 292 | 248 |
| 293 // Call CopyInForeignFile() on the dest_util_ with the resolved source path | 249 // Call CopyInForeignFile() on the dest_util_ with the resolved source path |
| 294 // to perform limited cross-FileSystemFileUtil copy/move. | 250 // to perform limited cross-FileSystemFileUtil copy/move. |
| 295 error = dest_util_->CopyInForeignFile( | 251 error = dest_util_->CopyInForeignFile( |
| 296 context_, platform_file_path, dest_url); | 252 context_, platform_file_path, dest_url); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 } | 297 } |
| 342 | 298 |
| 343 // static | 299 // static |
| 344 base::PlatformFileError FileUtilHelper::Delete( | 300 base::PlatformFileError FileUtilHelper::Delete( |
| 345 FileSystemOperationContext* context, | 301 FileSystemOperationContext* context, |
| 346 FileSystemFileUtil* file_util, | 302 FileSystemFileUtil* file_util, |
| 347 const FileSystemURL& url, | 303 const FileSystemURL& url, |
| 348 bool recursive) { | 304 bool recursive) { |
| 349 if (DirectoryExists(context, file_util, url)) { | 305 if (DirectoryExists(context, file_util, url)) { |
| 350 if (!recursive) | 306 if (!recursive) |
| 351 return file_util->DeleteSingleDirectory(context, url); | 307 return file_util->DeleteDirectory(context, url); |
| 352 else | 308 else |
| 353 return DeleteDirectoryRecursive(context, file_util, url); | 309 return DeleteDirectoryRecursive(context, file_util, url); |
| 354 } else { | 310 } else { |
| 355 return file_util->DeleteFile(context, url); | 311 return file_util->DeleteFile(context, url); |
| 356 } | 312 } |
| 357 } | 313 } |
| 358 | 314 |
| 359 // static | 315 // static |
| 360 base::PlatformFileError FileUtilHelper::ReadDirectory( | 316 base::PlatformFileError FileUtilHelper::ReadDirectory( |
| 361 FileSystemOperationContext* context, | 317 FileSystemOperationContext* context, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 } else { | 355 } else { |
| 400 PlatformFileError error = file_util->DeleteFile( | 356 PlatformFileError error = file_util->DeleteFile( |
| 401 context, url.WithPath(file_path_each)); | 357 context, url.WithPath(file_path_each)); |
| 402 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && | 358 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && |
| 403 error != base::PLATFORM_FILE_OK) | 359 error != base::PLATFORM_FILE_OK) |
| 404 return error; | 360 return error; |
| 405 } | 361 } |
| 406 } | 362 } |
| 407 | 363 |
| 408 while (!directories.empty()) { | 364 while (!directories.empty()) { |
| 409 PlatformFileError error = file_util->DeleteSingleDirectory( | 365 PlatformFileError error = file_util->DeleteDirectory( |
| 410 context, url.WithPath(directories.top())); | 366 context, url.WithPath(directories.top())); |
| 411 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && | 367 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && |
| 412 error != base::PLATFORM_FILE_OK) | 368 error != base::PLATFORM_FILE_OK) |
| 413 return error; | 369 return error; |
| 414 directories.pop(); | 370 directories.pop(); |
| 415 } | 371 } |
| 416 return file_util->DeleteSingleDirectory(context, url); | 372 return file_util->DeleteDirectory(context, url); |
| 417 } | 373 } |
| 418 | 374 |
| 419 } // namespace fileapi | 375 } // namespace fileapi |
| OLD | NEW |