Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: webkit/fileapi/file_util_helper.cc

Issue 12051010: (For-try) Divide recursive Copy/Move into multiple async tasks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: test fix Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_ERROR_NOT_A_FILE)
178 // on all platforms, so we delete the destination directory here. 126 return error;
179 if (base::PLATFORM_FILE_OK != 127
180 dest_util_->DeleteSingleDirectory(context_, dest_root_url_)) { 128 // Now we should be sure that the source (and destination if exists)
181 if (!dest_util_->IsDirectoryEmpty(context_, dest_root_url_)) 129 // is directory.
182 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; 130 // Now let's try to remove the destination directory, this must
183 return base::PLATFORM_FILE_ERROR_FAILED; 131 // fail if the directory isn't empty or its parent doesn't exist.
184 } 132 error = dest_util_->DeleteDirectory(context_, dest_root_url_);
185 } 133 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY)
186 return base::PLATFORM_FILE_OK; 134 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
135 if (error != base::PLATFORM_FILE_OK &&
136 error != base::PLATFORM_FILE_ERROR_NOT_FOUND)
137 return error;
138
139 // Perform the actual work for directory copy/move.
140 return CopyOrMoveDirectory(src_root_url_, dest_root_url_);
187 } 141 }
188 142
189 PlatformFileError CrossFileUtilHelper::CopyOrMoveDirectory( 143 PlatformFileError CrossFileUtilHelper::CopyOrMoveDirectory(
190 const FileSystemURL& src_url, 144 const FileSystemURL& src_url,
191 const FileSystemURL& dest_url) { 145 const FileSystemURL& dest_url) {
192 // At this point we must have gone through 146 // At this point we must have gone through
193 // PerformErrorCheckAndPreparationForMoveAndCopy so this must be true. 147 // PerformErrorCheckAndPreparationForMoveAndCopy so this must be true.
194 DCHECK(!same_file_system_ || 148 DCHECK(!same_file_system_ ||
195 !src_url.path().IsParent(dest_url.path())); 149 !src_url.path().IsParent(dest_url.path()));
196 150
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 base::PlatformFileInfo file_info; 231 base::PlatformFileInfo file_info;
278 FilePath platform_file_path; 232 FilePath platform_file_path;
279 FileSystemFileUtil::SnapshotFilePolicy snapshot_policy; 233 FileSystemFileUtil::SnapshotFilePolicy snapshot_policy;
280 234
281 PlatformFileError error = src_util_->CreateSnapshotFile( 235 PlatformFileError error = src_util_->CreateSnapshotFile(
282 context_, src_url, &file_info, &platform_file_path, &snapshot_policy); 236 context_, src_url, &file_info, &platform_file_path, &snapshot_policy);
283 if (error != base::PLATFORM_FILE_OK) 237 if (error != base::PLATFORM_FILE_OK)
284 return error; 238 return error;
285 239
286 // For now we don't support non-snapshot file case. 240 // For now we don't support non-snapshot file case.
241 // TODO(kinuko): Address this case too.
287 DCHECK(!platform_file_path.empty()); 242 DCHECK(!platform_file_path.empty());
288 243
289 scoped_ptr<ScopedFileDeleter> file_deleter; 244 scoped_ptr<ScopedFileDeleter> file_deleter;
290 if (snapshot_policy == FileSystemFileUtil::kSnapshotFileTemporary) 245 if (snapshot_policy == FileSystemFileUtil::kSnapshotFileTemporary)
291 file_deleter.reset(new ScopedFileDeleter(platform_file_path)); 246 file_deleter.reset(new ScopedFileDeleter(platform_file_path));
292 247
293 // Call CopyInForeignFile() on the dest_util_ with the resolved source path 248 // Call CopyInForeignFile() on the dest_util_ with the resolved source path
294 // to perform limited cross-FileSystemFileUtil copy/move. 249 // to perform limited cross-FileSystemFileUtil copy/move.
295 error = dest_util_->CopyInForeignFile( 250 error = dest_util_->CopyInForeignFile(
296 context_, platform_file_path, dest_url); 251 context_, platform_file_path, dest_url);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 296 }
342 297
343 // static 298 // static
344 base::PlatformFileError FileUtilHelper::Delete( 299 base::PlatformFileError FileUtilHelper::Delete(
345 FileSystemOperationContext* context, 300 FileSystemOperationContext* context,
346 FileSystemFileUtil* file_util, 301 FileSystemFileUtil* file_util,
347 const FileSystemURL& url, 302 const FileSystemURL& url,
348 bool recursive) { 303 bool recursive) {
349 if (DirectoryExists(context, file_util, url)) { 304 if (DirectoryExists(context, file_util, url)) {
350 if (!recursive) 305 if (!recursive)
351 return file_util->DeleteSingleDirectory(context, url); 306 return file_util->DeleteDirectory(context, url);
352 else 307 else
353 return DeleteDirectoryRecursive(context, file_util, url); 308 return DeleteDirectoryRecursive(context, file_util, url);
354 } else { 309 } else {
355 return file_util->DeleteFile(context, url); 310 return file_util->DeleteFile(context, url);
356 } 311 }
357 } 312 }
358 313
359 // static 314 // static
360 base::PlatformFileError FileUtilHelper::ReadDirectory( 315 base::PlatformFileError FileUtilHelper::ReadDirectory(
361 FileSystemOperationContext* context, 316 FileSystemOperationContext* context,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 } else { 359 } else {
405 PlatformFileError error = file_util->DeleteFile( 360 PlatformFileError error = file_util->DeleteFile(
406 context, url.WithPath(file_path_each)); 361 context, url.WithPath(file_path_each));
407 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && 362 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND &&
408 error != base::PLATFORM_FILE_OK) 363 error != base::PLATFORM_FILE_OK)
409 return error; 364 return error;
410 } 365 }
411 } 366 }
412 367
413 while (!directories.empty()) { 368 while (!directories.empty()) {
414 PlatformFileError error = file_util->DeleteSingleDirectory( 369 PlatformFileError error = file_util->DeleteDirectory(
415 context, url.WithPath(directories.top())); 370 context, url.WithPath(directories.top()));
416 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && 371 if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND &&
417 error != base::PLATFORM_FILE_OK) 372 error != base::PLATFORM_FILE_OK)
418 return error; 373 return error;
419 directories.pop(); 374 directories.pop();
420 } 375 }
421 return file_util->DeleteSingleDirectory(context, url); 376 return file_util->DeleteDirectory(context, url);
422 } 377 }
423 378
424 } // namespace fileapi 379 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698