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" |
11 #include "base/scoped_ptr.h" | 11 #include "base/scoped_ptr.h" |
12 #include "webkit/fileapi/file_system_operation_context.h" | 12 #include "webkit/fileapi/file_system_operation_context.h" |
13 | 13 |
14 namespace fileapi { | 14 namespace fileapi { |
15 | 15 |
| 16 namespace { |
| 17 |
| 18 // This assumes that the root exists. |
| 19 bool ParentExists(FileSystemOperationContext* context, |
| 20 FileSystemFileUtil* file_util, const FilePath& file_path) { |
| 21 // If file_path is in the root, file_path.DirName() will be ".", |
| 22 // since we use paths with no leading '/'. |
| 23 FilePath parent = file_path.DirName(); |
| 24 if (parent == FilePath(FILE_PATH_LITERAL("."))) |
| 25 return true; |
| 26 return file_util->DirectoryExists(context, parent); |
| 27 } |
| 28 |
| 29 } |
| 30 |
16 // static | 31 // static |
17 FileSystemFileUtil* FileSystemFileUtil::GetInstance() { | 32 FileSystemFileUtil* FileSystemFileUtil::GetInstance() { |
18 return Singleton<FileSystemFileUtil>::get(); | 33 return Singleton<FileSystemFileUtil>::get(); |
19 } | 34 } |
20 | 35 |
21 PlatformFileError FileSystemFileUtil::CreateOrOpen( | 36 PlatformFileError FileSystemFileUtil::CreateOrOpen( |
22 FileSystemOperationContext* unused, | 37 FileSystemOperationContext* unused, |
23 const FilePath& file_path, int file_flags, | 38 const FilePath& file_path, int file_flags, |
24 PlatformFile* file_handle, bool* created) { | 39 PlatformFile* file_handle, bool* created) { |
25 if (!file_util::DirectoryExists(file_path.DirName())) { | 40 if (!file_util::DirectoryExists(file_path.DirName())) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 PlatformFileError error_code; | 156 PlatformFileError error_code; |
142 error_code = | 157 error_code = |
143 PerformCommonCheckAndPreparationForMoveAndCopy( | 158 PerformCommonCheckAndPreparationForMoveAndCopy( |
144 context, src_file_path, dest_file_path); | 159 context, src_file_path, dest_file_path); |
145 if (error_code != base::PLATFORM_FILE_OK) | 160 if (error_code != base::PLATFORM_FILE_OK) |
146 return error_code; | 161 return error_code; |
147 | 162 |
148 if (DirectoryExists(context, src_file_path)) | 163 if (DirectoryExists(context, src_file_path)) |
149 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | 164 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, |
150 true /* copy */); | 165 true /* copy */); |
151 else | 166 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, |
152 return CopyOrMoveFile(context, src_file_path, dest_file_path, | 167 true /* copy */); |
153 true /* copy */); | |
154 } | 168 } |
155 | 169 |
156 PlatformFileError FileSystemFileUtil::Move( | 170 PlatformFileError FileSystemFileUtil::Move( |
157 FileSystemOperationContext* context, | 171 FileSystemOperationContext* context, |
158 const FilePath& src_file_path, | 172 const FilePath& src_file_path, |
159 const FilePath& dest_file_path) { | 173 const FilePath& dest_file_path) { |
160 PlatformFileError error_code; | 174 PlatformFileError error_code; |
161 error_code = | 175 error_code = |
162 PerformCommonCheckAndPreparationForMoveAndCopy( | 176 PerformCommonCheckAndPreparationForMoveAndCopy( |
163 context, src_file_path, dest_file_path); | 177 context, src_file_path, dest_file_path); |
164 if (error_code != base::PLATFORM_FILE_OK) | 178 if (error_code != base::PLATFORM_FILE_OK) |
165 return error_code; | 179 return error_code; |
166 | 180 |
167 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. | 181 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. |
168 if (DirectoryExists(context, src_file_path)) | 182 if (DirectoryExists(context, src_file_path)) |
169 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | 183 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, |
170 false /* copy */); | 184 false /* copy */); |
171 else | 185 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, |
172 return CopyOrMoveFile(context, src_file_path, dest_file_path, | 186 false /* copy */); |
173 false /* copy */); | |
174 } | 187 } |
175 | 188 |
176 PlatformFileError FileSystemFileUtil::Delete( | 189 PlatformFileError FileSystemFileUtil::Delete( |
177 FileSystemOperationContext* context, | 190 FileSystemOperationContext* context, |
178 const FilePath& file_path, | 191 const FilePath& file_path, |
179 bool recursive) { | 192 bool recursive) { |
180 if (DirectoryExists(context, file_path)) { | 193 if (DirectoryExists(context, file_path)) { |
181 if (!recursive) | 194 if (!recursive) |
182 return DeleteSingleDirectory(context, file_path); | 195 return DeleteSingleDirectory(context, file_path); |
183 else | 196 else |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 error_code = base::PLATFORM_FILE_ERROR_FAILED; | 228 error_code = base::PLATFORM_FILE_ERROR_FAILED; |
216 base::ClosePlatformFile(file); | 229 base::ClosePlatformFile(file); |
217 return error_code; | 230 return error_code; |
218 } | 231 } |
219 | 232 |
220 PlatformFileError | 233 PlatformFileError |
221 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( | 234 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( |
222 FileSystemOperationContext* context, | 235 FileSystemOperationContext* context, |
223 const FilePath& src_file_path, | 236 const FilePath& src_file_path, |
224 const FilePath& dest_file_path) { | 237 const FilePath& dest_file_path) { |
| 238 bool same_file_system = |
| 239 (context->src_origin_url() == context->dest_origin_url()) && |
| 240 (context->src_type() == context->dest_type()); |
| 241 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); |
| 242 DCHECK(dest_util); |
| 243 FileSystemOperationContext local_dest_context( |
| 244 context->file_system_context(), dest_util); |
| 245 FileSystemOperationContext* dest_context; |
| 246 if (same_file_system) { |
| 247 dest_context = context; |
| 248 DCHECK(context->src_file_system_file_util() == |
| 249 context->dest_file_system_file_util()); |
| 250 } else { |
| 251 // All the single-path virtual FSFU methods expect the context information |
| 252 // to be in the src_* variables, not the dest_* variables, so we have to |
| 253 // make a new context if we want to call them on the dest_file_path. |
| 254 dest_context = &local_dest_context; |
| 255 dest_context->set_src_type(context->dest_type()); |
| 256 dest_context->set_src_origin_url(context->dest_origin_url()); |
| 257 dest_context->set_src_virtual_path(context->dest_virtual_path()); |
| 258 dest_context->set_allowed_bytes_growth(context->allowed_bytes_growth()); |
| 259 } |
| 260 |
225 // Exits earlier if the source path does not exist. | 261 // Exits earlier if the source path does not exist. |
226 if (!PathExists(context, src_file_path)) | 262 if (!PathExists(context, src_file_path)) |
227 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 263 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
228 | 264 |
229 // The parent of the |dest_file_path| does not exist. | 265 // The parent of the |dest_file_path| does not exist. |
230 if (!DirectoryExists(context, dest_file_path.DirName())) | 266 if (!ParentExists(dest_context, dest_util, dest_file_path)) |
231 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 267 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
232 | 268 |
233 // It is an error to try to copy/move an entry into its child. | 269 // It is an error to try to copy/move an entry into its child. |
234 if (src_file_path.IsParent(dest_file_path)) | 270 if (same_file_system && src_file_path.IsParent(dest_file_path)) |
235 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 271 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
236 | 272 |
237 // Now it is ok to return if the |dest_file_path| does not exist. | 273 // Now it is ok to return if the |dest_file_path| does not exist. |
238 if (!PathExists(context, dest_file_path)) | 274 if (!dest_util->PathExists(dest_context, dest_file_path)) |
239 return base::PLATFORM_FILE_OK; | 275 return base::PLATFORM_FILE_OK; |
240 | 276 |
241 // |src_file_path| exists and is a directory. | 277 // |src_file_path| exists and is a directory. |
242 // |dest_file_path| exists and is a file. | 278 // |dest_file_path| exists and is a file. |
243 bool src_is_directory = DirectoryExists(context, src_file_path); | 279 bool src_is_directory = DirectoryExists(context, src_file_path); |
244 bool dest_is_directory = DirectoryExists(context, dest_file_path); | 280 bool dest_is_directory = |
| 281 dest_util->DirectoryExists(dest_context, dest_file_path); |
245 if (src_is_directory && !dest_is_directory) | 282 if (src_is_directory && !dest_is_directory) |
246 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 283 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
247 | 284 |
248 // |src_file_path| exists and is a file. | 285 // |src_file_path| exists and is a file. |
249 // |dest_file_path| exists and is a directory. | 286 // |dest_file_path| exists and is a directory. |
250 if (!src_is_directory && dest_is_directory) | 287 if (!src_is_directory && dest_is_directory) |
251 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 288 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
252 | 289 |
253 // It is an error to copy/move an entry into the same path. | 290 // It is an error to copy/move an entry into the same path. |
254 if (src_file_path.value() == dest_file_path.value()) | 291 if (same_file_system && (src_file_path.value() == dest_file_path.value())) |
255 return base::PLATFORM_FILE_ERROR_EXISTS; | 292 return base::PLATFORM_FILE_ERROR_EXISTS; |
256 | 293 |
257 if (dest_is_directory) { | 294 if (dest_is_directory) { |
258 // It is an error to copy/move an entry to a non-empty directory. | 295 // 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 | 296 // Otherwise the copy/move attempt must overwrite the destination, but |
260 // the file_util's Copy or Move method doesn't perform overwrite | 297 // the file_util's Copy or Move method doesn't perform overwrite |
261 // on all platforms, so we delete the destination directory here. | 298 // on all platforms, so we delete the destination directory here. |
262 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. | 299 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. |
263 if (base::PLATFORM_FILE_OK != | 300 if (base::PLATFORM_FILE_OK != |
264 Delete(context, dest_file_path, false /* recursive */)) { | 301 dest_util->Delete(dest_context, dest_file_path, |
265 if (!IsDirectoryEmpty(context, dest_file_path)) | 302 false /* recursive */)) { |
| 303 if (!dest_util->IsDirectoryEmpty(dest_context, dest_file_path)) |
266 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 304 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
267 return base::PLATFORM_FILE_ERROR_FAILED; | 305 return base::PLATFORM_FILE_ERROR_FAILED; |
268 } | 306 } |
269 } | 307 } |
270 return base::PLATFORM_FILE_OK; | 308 return base::PLATFORM_FILE_OK; |
271 } | 309 } |
272 | 310 |
273 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( | 311 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( |
274 FileSystemOperationContext* unused, | 312 FileSystemOperationContext* unused, |
275 const FilePath& src_file_path, | 313 const FilePath& src_file_path, |
276 const FilePath& dest_file_path, | 314 const FilePath& dest_file_path, |
277 bool copy) { | 315 bool copy) { |
278 if (copy) { | 316 if (copy) { |
279 if (file_util::CopyFile(src_file_path, dest_file_path)) | 317 if (file_util::CopyFile(src_file_path, dest_file_path)) |
280 return base::PLATFORM_FILE_OK; | 318 return base::PLATFORM_FILE_OK; |
281 } else { | 319 } else { |
282 DCHECK(!file_util::DirectoryExists(src_file_path)); | 320 DCHECK(!file_util::DirectoryExists(src_file_path)); |
283 if (file_util::Move(src_file_path, dest_file_path)) | 321 if (file_util::Move(src_file_path, dest_file_path)) |
284 return base::PLATFORM_FILE_OK; | 322 return base::PLATFORM_FILE_OK; |
285 } | 323 } |
286 return base::PLATFORM_FILE_ERROR_FAILED; | 324 return base::PLATFORM_FILE_ERROR_FAILED; |
287 } | 325 } |
288 | 326 |
| 327 PlatformFileError FileSystemFileUtil::CopyInForeignFile( |
| 328 FileSystemOperationContext* context, |
| 329 const FilePath& src_file_path, |
| 330 const FilePath& dest_file_path) { |
| 331 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); |
| 332 } |
| 333 |
289 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( | 334 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( |
290 FileSystemOperationContext* context, | 335 FileSystemOperationContext* context, |
291 const FilePath& src_file_path, | 336 const FilePath& src_file_path, |
292 const FilePath& dest_file_path, | 337 const FilePath& dest_file_path, |
293 bool copy) { | 338 bool copy) { |
| 339 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); |
| 340 FileSystemOperationContext dest_context( |
| 341 context->file_system_context(), dest_util); |
| 342 // All the single-path virtual FSFU methods expect the context information to |
| 343 // be in the src_* variables, not the dest_* variables, so we have to make a |
| 344 // new context if we want to call them on the dest_file_path. |
| 345 dest_context.set_src_type(context->dest_type()); |
| 346 dest_context.set_src_origin_url(context->dest_origin_url()); |
| 347 dest_context.set_src_virtual_path(context->dest_virtual_path()); |
| 348 dest_context.set_allowed_bytes_growth(context->allowed_bytes_growth()); |
| 349 |
294 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. | 350 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. |
295 DCHECK(DirectoryExists(context, src_file_path)); | 351 DCHECK(DirectoryExists(context, src_file_path)); |
296 DCHECK(DirectoryExists(context, dest_file_path.DirName())); | 352 DCHECK(ParentExists(&dest_context, dest_util, dest_file_path)); |
297 DCHECK(!src_file_path.IsParent(dest_file_path)); | 353 DCHECK(!dest_util->PathExists(&dest_context, dest_file_path)); |
298 DCHECK(!PathExists(context, dest_file_path)); | 354 if ((context->src_origin_url() == context->dest_origin_url()) && |
| 355 (context->src_type() == context->dest_type())) |
| 356 DCHECK(!src_file_path.IsParent(dest_file_path)); |
299 | 357 |
300 if (!DirectoryExists(context, dest_file_path)) { | 358 if (!dest_util->DirectoryExists(&dest_context, dest_file_path)) { |
301 PlatformFileError error = CreateDirectory(context, | 359 PlatformFileError error = dest_util->CreateDirectory(&dest_context, |
302 dest_file_path, false, false); | 360 dest_file_path, false, false); |
303 if (error != base::PLATFORM_FILE_OK) | 361 if (error != base::PLATFORM_FILE_OK) |
304 return error; | 362 return error; |
305 } | 363 } |
306 | 364 |
307 scoped_ptr<AbstractFileEnumerator> file_enum( | 365 scoped_ptr<AbstractFileEnumerator> file_enum( |
308 CreateFileEnumerator(context, src_file_path)); | 366 CreateFileEnumerator(context, src_file_path)); |
309 FilePath src_file_path_each; | 367 FilePath src_file_path_each; |
310 while (!(src_file_path_each = file_enum->Next()).empty()) { | 368 while (!(src_file_path_each = file_enum->Next()).empty()) { |
311 FilePath dest_file_path_each(dest_file_path); | 369 FilePath dest_file_path_each(dest_file_path); |
312 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); | 370 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); |
313 | 371 |
314 if (file_enum->IsDirectory()) { | 372 if (file_enum->IsDirectory()) { |
315 PlatformFileError error = CreateDirectory(context, | 373 PlatformFileError error = dest_util->CreateDirectory(&dest_context, |
316 dest_file_path_each, false, false); | 374 dest_file_path_each, false, false); |
317 if (error != base::PLATFORM_FILE_OK) | 375 if (error != base::PLATFORM_FILE_OK) |
318 return error; | 376 return error; |
319 } else { | 377 } else { |
320 // CopyOrMoveFile here is the virtual overridden member function. | 378 PlatformFileError error = CopyOrMoveFileHelper( |
321 PlatformFileError error = CopyOrMoveFile( | |
322 context, src_file_path_each, dest_file_path_each, copy); | 379 context, src_file_path_each, dest_file_path_each, copy); |
323 if (error != base::PLATFORM_FILE_OK) | 380 if (error != base::PLATFORM_FILE_OK) |
324 return error; | 381 return error; |
325 } | 382 } |
326 } | 383 } |
327 | 384 |
328 if (!copy) { | 385 if (!copy) { |
329 PlatformFileError error = Delete(context, src_file_path, true); | 386 PlatformFileError error = Delete(context, src_file_path, true); |
330 if (error != base::PLATFORM_FILE_OK) | 387 if (error != base::PLATFORM_FILE_OK) |
331 return error; | 388 return error; |
332 } | 389 } |
333 return base::PLATFORM_FILE_OK; | 390 return base::PLATFORM_FILE_OK; |
334 } | 391 } |
335 | 392 |
| 393 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper( |
| 394 FileSystemOperationContext* context, |
| 395 const FilePath& src_file_path, |
| 396 const FilePath& dest_file_path, |
| 397 bool copy) { |
| 398 // CopyOrMoveFile here is the virtual overridden member function. |
| 399 if ((context->src_origin_url() == context->dest_origin_url()) && |
| 400 (context->src_type() == context->dest_type())) { |
| 401 DCHECK(context->src_file_system_file_util() == |
| 402 context->dest_file_system_file_util()); |
| 403 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy); |
| 404 } |
| 405 base::PlatformFileInfo file_info; |
| 406 FilePath platform_file_path; |
| 407 PlatformFileError error_code; |
| 408 error_code = |
| 409 GetFileInfo(context, src_file_path, &file_info, &platform_file_path); |
| 410 if (error_code != base::PLATFORM_FILE_OK) |
| 411 return error_code; |
| 412 |
| 413 DCHECK(context->dest_file_system_file_util()); |
| 414 error_code = context->dest_file_system_file_util()->CopyInForeignFile( |
| 415 context, platform_file_path, dest_file_path); |
| 416 if (copy || error_code != base::PLATFORM_FILE_OK) |
| 417 return error_code; |
| 418 return DeleteFile(context, src_file_path); |
| 419 } |
| 420 |
| 421 |
336 PlatformFileError FileSystemFileUtil::DeleteFile( | 422 PlatformFileError FileSystemFileUtil::DeleteFile( |
337 FileSystemOperationContext* unused, | 423 FileSystemOperationContext* unused, |
338 const FilePath& file_path) { | 424 const FilePath& file_path) { |
339 if (!file_util::PathExists(file_path)) | 425 if (!file_util::PathExists(file_path)) |
340 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 426 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
341 if (file_util::DirectoryExists(file_path)) | 427 if (file_util::DirectoryExists(file_path)) |
342 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | 428 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
343 if (!file_util::Delete(file_path, false)) | 429 if (!file_util::Delete(file_path, false)) |
344 return base::PLATFORM_FILE_ERROR_FAILED; | 430 return base::PLATFORM_FILE_ERROR_FAILED; |
345 return base::PLATFORM_FILE_OK; | 431 return base::PLATFORM_FILE_OK; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 FileSystemFileUtil::CreateFileEnumerator( | 531 FileSystemFileUtil::CreateFileEnumerator( |
446 FileSystemOperationContext* unused, | 532 FileSystemOperationContext* unused, |
447 const FilePath& root_path) { | 533 const FilePath& root_path) { |
448 return new FileSystemFileEnumerator( | 534 return new FileSystemFileEnumerator( |
449 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( | 535 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( |
450 file_util::FileEnumerator::FILES | | 536 file_util::FileEnumerator::FILES | |
451 file_util::FileEnumerator::DIRECTORIES)); | 537 file_util::FileEnumerator::DIRECTORIES)); |
452 } | 538 } |
453 | 539 |
454 } // namespace fileapi | 540 } // namespace fileapi |
OLD | NEW |