OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_system_file_util.h" | 5 #include "webkit/fileapi/file_system_file_util.h" |
6 | 6 |
7 #include <stack> | 7 #include <stack> |
8 | 8 |
9 #include "base/file_util_proxy.h" | 9 #include "base/file_util_proxy.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 PlatformFileError error_code; | 141 PlatformFileError error_code; |
142 error_code = | 142 error_code = |
143 PerformCommonCheckAndPreparationForMoveAndCopy( | 143 PerformCommonCheckAndPreparationForMoveAndCopy( |
144 context, src_file_path, dest_file_path); | 144 context, src_file_path, dest_file_path); |
145 if (error_code != base::PLATFORM_FILE_OK) | 145 if (error_code != base::PLATFORM_FILE_OK) |
146 return error_code; | 146 return error_code; |
147 | 147 |
148 if (DirectoryExists(context, src_file_path)) | 148 if (DirectoryExists(context, src_file_path)) |
149 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | 149 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, |
150 true /* copy */); | 150 true /* copy */); |
151 else | 151 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, |
152 return CopyOrMoveFile(context, src_file_path, dest_file_path, | 152 true /* copy */); |
153 true /* copy */); | |
154 } | 153 } |
155 | 154 |
156 PlatformFileError FileSystemFileUtil::Move( | 155 PlatformFileError FileSystemFileUtil::Move( |
157 FileSystemOperationContext* context, | 156 FileSystemOperationContext* context, |
158 const FilePath& src_file_path, | 157 const FilePath& src_file_path, |
159 const FilePath& dest_file_path) { | 158 const FilePath& dest_file_path) { |
160 PlatformFileError error_code; | 159 PlatformFileError error_code; |
161 error_code = | 160 error_code = |
162 PerformCommonCheckAndPreparationForMoveAndCopy( | 161 PerformCommonCheckAndPreparationForMoveAndCopy( |
163 context, src_file_path, dest_file_path); | 162 context, src_file_path, dest_file_path); |
164 if (error_code != base::PLATFORM_FILE_OK) | 163 if (error_code != base::PLATFORM_FILE_OK) |
165 return error_code; | 164 return error_code; |
166 | 165 |
167 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. | 166 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. |
168 if (DirectoryExists(context, src_file_path)) | 167 if (DirectoryExists(context, src_file_path)) |
169 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | 168 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, |
170 false /* copy */); | 169 false /* copy */); |
171 else | 170 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, |
172 return CopyOrMoveFile(context, src_file_path, dest_file_path, | 171 false /* copy */); |
173 false /* copy */); | |
174 } | 172 } |
175 | 173 |
176 PlatformFileError FileSystemFileUtil::Delete( | 174 PlatformFileError FileSystemFileUtil::Delete( |
177 FileSystemOperationContext* context, | 175 FileSystemOperationContext* context, |
178 const FilePath& file_path, | 176 const FilePath& file_path, |
179 bool recursive) { | 177 bool recursive) { |
180 if (DirectoryExists(context, file_path)) { | 178 if (DirectoryExists(context, file_path)) { |
181 if (!recursive) | 179 if (!recursive) |
182 return DeleteSingleDirectory(context, file_path); | 180 return DeleteSingleDirectory(context, file_path); |
183 else | 181 else |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 error_code = base::PLATFORM_FILE_ERROR_FAILED; | 213 error_code = base::PLATFORM_FILE_ERROR_FAILED; |
216 base::ClosePlatformFile(file); | 214 base::ClosePlatformFile(file); |
217 return error_code; | 215 return error_code; |
218 } | 216 } |
219 | 217 |
220 PlatformFileError | 218 PlatformFileError |
221 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( | 219 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( |
222 FileSystemOperationContext* context, | 220 FileSystemOperationContext* context, |
223 const FilePath& src_file_path, | 221 const FilePath& src_file_path, |
224 const FilePath& dest_file_path) { | 222 const FilePath& dest_file_path) { |
223 bool same_file_system = | |
224 (context->src_origin_url() == context->dest_origin_url()) && | |
225 (context->src_type() == context->dest_type()); | |
226 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | |
227 DCHECK(dest_util); | |
228 FileSystemOperationContext local_dest_context( | |
michaeln
2011/05/25 19:27:57
A comment about why you need a local_dest_context
ericu
2011/05/25 19:56:20
Done.
| |
229 context->file_system_context(), dest_util); | |
230 FileSystemOperationContext* dest_context; | |
231 if (same_file_system) { | |
232 dest_context = context; | |
233 DCHECK(context->src_file_system_file_util() == | |
234 context->dest_file_system_file_util()); | |
235 } else { | |
236 dest_context = &local_dest_context; | |
237 dest_context->set_src_type(context->dest_type()); | |
238 dest_context->set_src_origin_url(context->dest_origin_url()); | |
239 dest_context->set_src_virtual_path(context->dest_virtual_path()); | |
240 dest_context->set_allowed_bytes_growth(context->allowed_bytes_growth()); | |
241 } | |
242 | |
225 // Exits earlier if the source path does not exist. | 243 // Exits earlier if the source path does not exist. |
226 if (!PathExists(context, src_file_path)) | 244 if (!PathExists(context, src_file_path)) |
227 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 245 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
228 | 246 |
229 // The parent of the |dest_file_path| does not exist. | 247 // The parent of the |dest_file_path| does not exist. |
230 if (!DirectoryExists(context, dest_file_path.DirName())) | 248 // If dest_file_path is in the root, dest_file_path.DirName() will be ".", |
249 // since we use paths with no leading '/'. | |
250 FilePath dest_parent = dest_file_path.DirName(); | |
251 if (dest_parent != FilePath(FILE_PATH_LITERAL(".")) && | |
michaeln
2011/05/25 19:27:57
I get it, but odd looking case testing for ".", ma
ericu
2011/05/25 19:56:20
Done: ParentExists().
| |
252 !dest_util->DirectoryExists(dest_context, dest_parent)) | |
231 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 253 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
232 | 254 |
233 // It is an error to try to copy/move an entry into its child. | 255 // It is an error to try to copy/move an entry into its child. |
234 if (src_file_path.IsParent(dest_file_path)) | 256 if (same_file_system && src_file_path.IsParent(dest_file_path)) |
235 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 257 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
236 | 258 |
237 // Now it is ok to return if the |dest_file_path| does not exist. | 259 // Now it is ok to return if the |dest_file_path| does not exist. |
238 if (!PathExists(context, dest_file_path)) | 260 if (!dest_util->PathExists(dest_context, dest_file_path)) |
239 return base::PLATFORM_FILE_OK; | 261 return base::PLATFORM_FILE_OK; |
240 | 262 |
241 // |src_file_path| exists and is a directory. | 263 // |src_file_path| exists and is a directory. |
242 // |dest_file_path| exists and is a file. | 264 // |dest_file_path| exists and is a file. |
243 bool src_is_directory = DirectoryExists(context, src_file_path); | 265 bool src_is_directory = DirectoryExists(context, src_file_path); |
244 bool dest_is_directory = DirectoryExists(context, dest_file_path); | 266 bool dest_is_directory = |
267 dest_util->DirectoryExists(dest_context, dest_file_path); | |
245 if (src_is_directory && !dest_is_directory) | 268 if (src_is_directory && !dest_is_directory) |
246 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 269 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
247 | 270 |
248 // |src_file_path| exists and is a file. | 271 // |src_file_path| exists and is a file. |
249 // |dest_file_path| exists and is a directory. | 272 // |dest_file_path| exists and is a directory. |
250 if (!src_is_directory && dest_is_directory) | 273 if (!src_is_directory && dest_is_directory) |
251 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 274 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
252 | 275 |
253 // It is an error to copy/move an entry into the same path. | 276 // It is an error to copy/move an entry into the same path. |
254 if (src_file_path.value() == dest_file_path.value()) | 277 if (same_file_system && (src_file_path.value() == dest_file_path.value())) |
255 return base::PLATFORM_FILE_ERROR_EXISTS; | 278 return base::PLATFORM_FILE_ERROR_EXISTS; |
256 | 279 |
257 if (dest_is_directory) { | 280 if (dest_is_directory) { |
258 // It is an error to copy/move an entry to a non-empty directory. | 281 // It is an error to copy/move an entry to a non-empty directory. |
259 // Otherwise the copy/move attempt must overwrite the destination, but | 282 // Otherwise the copy/move attempt must overwrite the destination, but |
260 // the file_util's Copy or Move method doesn't perform overwrite | 283 // the file_util's Copy or Move method doesn't perform overwrite |
261 // on all platforms, so we delete the destination directory here. | 284 // on all platforms, so we delete the destination directory here. |
262 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. | 285 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. |
263 if (base::PLATFORM_FILE_OK != | 286 if (base::PLATFORM_FILE_OK != |
264 Delete(context, dest_file_path, false /* recursive */)) { | 287 dest_util->Delete(dest_context, dest_file_path, |
265 if (!IsDirectoryEmpty(context, dest_file_path)) | 288 false /* recursive */)) { |
289 if (!dest_util->IsDirectoryEmpty(dest_context, dest_file_path)) | |
266 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 290 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
267 return base::PLATFORM_FILE_ERROR_FAILED; | 291 return base::PLATFORM_FILE_ERROR_FAILED; |
268 } | 292 } |
269 } | 293 } |
270 return base::PLATFORM_FILE_OK; | 294 return base::PLATFORM_FILE_OK; |
271 } | 295 } |
272 | 296 |
273 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( | 297 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( |
274 FileSystemOperationContext* unused, | 298 FileSystemOperationContext* unused, |
275 const FilePath& src_file_path, | 299 const FilePath& src_file_path, |
276 const FilePath& dest_file_path, | 300 const FilePath& dest_file_path, |
277 bool copy) { | 301 bool copy) { |
278 if (copy) { | 302 if (copy) { |
279 if (file_util::CopyFile(src_file_path, dest_file_path)) | 303 if (file_util::CopyFile(src_file_path, dest_file_path)) |
280 return base::PLATFORM_FILE_OK; | 304 return base::PLATFORM_FILE_OK; |
281 } else { | 305 } else { |
282 DCHECK(!file_util::DirectoryExists(src_file_path)); | 306 DCHECK(!file_util::DirectoryExists(src_file_path)); |
283 if (file_util::Move(src_file_path, dest_file_path)) | 307 if (file_util::Move(src_file_path, dest_file_path)) |
284 return base::PLATFORM_FILE_OK; | 308 return base::PLATFORM_FILE_OK; |
285 } | 309 } |
286 return base::PLATFORM_FILE_ERROR_FAILED; | 310 return base::PLATFORM_FILE_ERROR_FAILED; |
287 } | 311 } |
288 | 312 |
313 PlatformFileError FileSystemFileUtil::CopyInForeignFile( | |
314 FileSystemOperationContext* context, | |
315 const FilePath& src_file_path, | |
316 const FilePath& dest_file_path) { | |
317 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); | |
318 } | |
319 | |
289 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( | 320 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( |
290 FileSystemOperationContext* context, | 321 FileSystemOperationContext* context, |
291 const FilePath& src_file_path, | 322 const FilePath& src_file_path, |
292 const FilePath& dest_file_path, | 323 const FilePath& dest_file_path, |
293 bool copy) { | 324 bool copy) { |
325 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | |
326 FileSystemOperationContext dest_context( | |
327 context->file_system_context(), dest_util); | |
328 dest_context.set_src_type(context->dest_type()); | |
329 dest_context.set_src_origin_url(context->dest_origin_url()); | |
330 dest_context.set_src_virtual_path(context->dest_virtual_path()); | |
331 dest_context.set_allowed_bytes_growth(context->allowed_bytes_growth()); | |
332 | |
294 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. | 333 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. |
295 DCHECK(DirectoryExists(context, src_file_path)); | 334 DCHECK(DirectoryExists(context, src_file_path)); |
296 DCHECK(DirectoryExists(context, dest_file_path.DirName())); | 335 DCHECK((dest_file_path.DirName() == FilePath(FILE_PATH_LITERAL("."))) || |
297 DCHECK(!src_file_path.IsParent(dest_file_path)); | 336 dest_util->DirectoryExists(&dest_context, dest_file_path.DirName())); |
298 DCHECK(!PathExists(context, dest_file_path)); | 337 DCHECK(!dest_util->PathExists(&dest_context, dest_file_path)); |
338 if ((context->src_origin_url() == context->dest_origin_url()) && | |
339 (context->src_type() == context->dest_type())) | |
340 DCHECK(!src_file_path.IsParent(dest_file_path)); | |
299 | 341 |
300 if (!DirectoryExists(context, dest_file_path)) { | 342 if (!dest_util->DirectoryExists(&dest_context, dest_file_path)) { |
301 PlatformFileError error = CreateDirectory(context, | 343 PlatformFileError error = dest_util->CreateDirectory(&dest_context, |
302 dest_file_path, false, false); | 344 dest_file_path, false, false); |
303 if (error != base::PLATFORM_FILE_OK) | 345 if (error != base::PLATFORM_FILE_OK) |
304 return error; | 346 return error; |
305 } | 347 } |
306 | 348 |
307 scoped_ptr<AbstractFileEnumerator> file_enum( | 349 scoped_ptr<AbstractFileEnumerator> file_enum( |
308 CreateFileEnumerator(context, src_file_path)); | 350 CreateFileEnumerator(context, src_file_path)); |
309 FilePath src_file_path_each; | 351 FilePath src_file_path_each; |
310 while (!(src_file_path_each = file_enum->Next()).empty()) { | 352 while (!(src_file_path_each = file_enum->Next()).empty()) { |
311 FilePath dest_file_path_each(dest_file_path); | 353 FilePath dest_file_path_each(dest_file_path); |
312 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); | 354 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); |
313 | 355 |
314 if (file_enum->IsDirectory()) { | 356 if (file_enum->IsDirectory()) { |
315 PlatformFileError error = CreateDirectory(context, | 357 PlatformFileError error = dest_util->CreateDirectory(&dest_context, |
316 dest_file_path_each, false, false); | 358 dest_file_path_each, false, false); |
317 if (error != base::PLATFORM_FILE_OK) | 359 if (error != base::PLATFORM_FILE_OK) |
318 return error; | 360 return error; |
319 } else { | 361 } else { |
320 // CopyOrMoveFile here is the virtual overridden member function. | 362 PlatformFileError error = CopyOrMoveFileHelper( |
321 PlatformFileError error = CopyOrMoveFile( | |
322 context, src_file_path_each, dest_file_path_each, copy); | 363 context, src_file_path_each, dest_file_path_each, copy); |
323 if (error != base::PLATFORM_FILE_OK) | 364 if (error != base::PLATFORM_FILE_OK) |
324 return error; | 365 return error; |
325 } | 366 } |
326 } | 367 } |
327 | 368 |
328 if (!copy) { | 369 if (!copy) { |
329 PlatformFileError error = Delete(context, src_file_path, true); | 370 PlatformFileError error = Delete(context, src_file_path, true); |
330 if (error != base::PLATFORM_FILE_OK) | 371 if (error != base::PLATFORM_FILE_OK) |
331 return error; | 372 return error; |
332 } | 373 } |
333 return base::PLATFORM_FILE_OK; | 374 return base::PLATFORM_FILE_OK; |
334 } | 375 } |
335 | 376 |
377 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper( | |
378 FileSystemOperationContext* context, | |
379 const FilePath& src_file_path, | |
380 const FilePath& dest_file_path, | |
381 bool copy) { | |
382 // CopyOrMoveFile here is the virtual overridden member function. | |
383 if ((context->src_origin_url() == context->dest_origin_url()) && | |
384 (context->src_type() == context->dest_type())) { | |
385 DCHECK(context->src_file_system_file_util() == | |
386 context->dest_file_system_file_util()); | |
387 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy); | |
388 } | |
389 base::PlatformFileInfo file_info; | |
390 FilePath platform_file_path; | |
391 PlatformFileError error_code; | |
392 error_code = | |
393 GetFileInfo(context, src_file_path, &file_info, &platform_file_path); | |
394 if (error_code != base::PLATFORM_FILE_OK) | |
395 return error_code; | |
396 | |
397 DCHECK(context->dest_file_system_file_util()); | |
398 error_code = context->dest_file_system_file_util()->CopyInForeignFile( | |
399 context, platform_file_path, dest_file_path); | |
400 if (copy || error_code != base::PLATFORM_FILE_OK) | |
401 return error_code; | |
402 return DeleteFile(context, src_file_path); | |
403 } | |
404 | |
405 | |
336 PlatformFileError FileSystemFileUtil::DeleteFile( | 406 PlatformFileError FileSystemFileUtil::DeleteFile( |
337 FileSystemOperationContext* unused, | 407 FileSystemOperationContext* unused, |
338 const FilePath& file_path) { | 408 const FilePath& file_path) { |
339 if (!file_util::PathExists(file_path)) | 409 if (!file_util::PathExists(file_path)) |
340 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 410 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
341 if (file_util::DirectoryExists(file_path)) | 411 if (file_util::DirectoryExists(file_path)) |
342 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | 412 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
343 if (!file_util::Delete(file_path, false)) | 413 if (!file_util::Delete(file_path, false)) |
344 return base::PLATFORM_FILE_ERROR_FAILED; | 414 return base::PLATFORM_FILE_ERROR_FAILED; |
345 return base::PLATFORM_FILE_OK; | 415 return base::PLATFORM_FILE_OK; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 FileSystemFileUtil::CreateFileEnumerator( | 515 FileSystemFileUtil::CreateFileEnumerator( |
446 FileSystemOperationContext* unused, | 516 FileSystemOperationContext* unused, |
447 const FilePath& root_path) { | 517 const FilePath& root_path) { |
448 return new FileSystemFileEnumerator( | 518 return new FileSystemFileEnumerator( |
449 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( | 519 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( |
450 file_util::FileEnumerator::FILES | | 520 file_util::FileEnumerator::FILES | |
451 file_util::FileEnumerator::DIRECTORIES)); | 521 file_util::FileEnumerator::DIRECTORIES)); |
452 } | 522 } |
453 | 523 |
454 } // namespace fileapi | 524 } // namespace fileapi |
OLD | NEW |