| 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/fileapi/cross_operation_delegate.h" | 5 #include "webkit/fileapi/cross_operation_delegate.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "webkit/blob/shareable_file_reference.h" | 8 #include "webkit/blob/shareable_file_reference.h" |
| 9 #include "webkit/fileapi/copy_or_move_file_validator.h" | 9 #include "webkit/fileapi/copy_or_move_file_validator.h" |
| 10 #include "webkit/fileapi/file_system_context.h" | 10 #include "webkit/fileapi/file_system_context.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 return; | 48 return; |
| 49 } | 49 } |
| 50 | 50 |
| 51 // It is an error to copy/move an entry into the same path. | 51 // It is an error to copy/move an entry into the same path. |
| 52 if (same_file_system_ && src_root_.path() == dest_root_.path()) { | 52 if (same_file_system_ && src_root_.path() == dest_root_.path()) { |
| 53 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); | 53 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); |
| 54 return; | 54 return; |
| 55 } | 55 } |
| 56 | 56 |
| 57 // First try to copy/move it as a file. | 57 // First try to copy/move it as a file. |
| 58 CopyOrMoveFile(src_root_, dest_root_, | 58 Request request(src_root_, dest_root_, |
| 59 base::Bind(&CrossOperationDelegate::DidTryCopyOrMoveFile, | 59 base::Bind(&CrossOperationDelegate::DidTryCopyOrMoveFile, |
| 60 AsWeakPtr())); | 60 AsWeakPtr())); |
| 61 CopyOrMoveFile(request); |
| 61 } | 62 } |
| 62 | 63 |
| 63 void CrossOperationDelegate::ProcessFile(const FileSystemURL& src_url, | 64 void CrossOperationDelegate::ProcessFile(const FileSystemURL& src_url, |
| 64 const StatusCallback& callback) { | 65 const StatusCallback& callback) { |
| 65 CopyOrMoveFile(src_url, CreateDestURL(src_url), callback); | 66 Request request(src_url, CreateDestURL(src_url), callback); |
| 67 CopyOrMoveFile(request); |
| 66 } | 68 } |
| 67 | 69 |
| 68 void CrossOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, | 70 void CrossOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, |
| 69 const StatusCallback& callback) { | 71 const StatusCallback& callback) { |
| 70 FileSystemURL dest_url = CreateDestURL(src_url); | 72 FileSystemURL dest_url = CreateDestURL(src_url); |
| 71 | 73 |
| 72 // If operation_type == Move we may need to record directories and | 74 // If operation_type == Move we may need to record directories and |
| 73 // restore directory timestamps in the end, though it may have | 75 // restore directory timestamps in the end, though it may have |
| 74 // negative performance impact. | 76 // negative performance impact. |
| 75 // See http://crbug.com/171284 for more details. | 77 // See http://crbug.com/171284 for more details. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 102 if (error != base::PLATFORM_FILE_OK && | 104 if (error != base::PLATFORM_FILE_OK && |
| 103 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { | 105 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
| 104 callback_.Run(error); | 106 callback_.Run(error); |
| 105 return; | 107 return; |
| 106 } | 108 } |
| 107 | 109 |
| 108 // Start to process the source directory recursively. | 110 // Start to process the source directory recursively. |
| 109 // TODO(kinuko): This could be too expensive for same_file_system_==true | 111 // TODO(kinuko): This could be too expensive for same_file_system_==true |
| 110 // and operation==MOVE case, probably we can just rename the root directory. | 112 // and operation==MOVE case, probably we can just rename the root directory. |
| 111 // http://crbug.com/172187 | 113 // http://crbug.com/172187 |
| 114 Request request(src_root_, dest_root_, callback_); |
| 112 StartRecursiveOperation( | 115 StartRecursiveOperation( |
| 113 src_root_, base::Bind(&CrossOperationDelegate::DidFinishCopy, | 116 src_root_, base::Bind(&CrossOperationDelegate::DidFinishCopy, |
| 114 AsWeakPtr(), src_root_, callback_)); | 117 AsWeakPtr(), request)); |
| 115 } | 118 } |
| 116 | 119 |
| 117 void CrossOperationDelegate::CopyOrMoveFile( | 120 void CrossOperationDelegate::CopyOrMoveFile(const Request& request) { |
| 118 const FileSystemURL& src, | |
| 119 const FileSystemURL& dest, | |
| 120 const StatusCallback& callback) { | |
| 121 // Same filesystem case. | 121 // Same filesystem case. |
| 122 if (same_file_system_) { | 122 if (same_file_system_) { |
| 123 if (operation_type_ == OPERATION_MOVE) | 123 if (operation_type_ == OPERATION_MOVE) { |
| 124 NewSourceOperation()->MoveFileLocal(src, dest, callback); | 124 NewSourceOperation()->MoveFileLocal(request.src, request.dest, |
| 125 else | 125 request.callback); |
| 126 NewSourceOperation()->CopyFileLocal(src, dest, callback); | 126 } else { |
| 127 NewSourceOperation()->CopyFileLocal(request.src, request.dest, |
| 128 request.callback); |
| 129 } |
| 127 return; | 130 return; |
| 128 } | 131 } |
| 129 | 132 |
| 130 // Cross filesystem case. | 133 // Cross filesystem case. |
| 131 // Perform CreateSnapshotFile, CopyInForeignFile and then calls | 134 // Perform CreateSnapshotFile, CopyInForeignFile and then calls |
| 132 // copy_callback which removes the source file if operation_type == MOVE. | 135 // copy_callback which removes the source file if operation_type == MOVE. |
| 133 StatusCallback copy_callback = | 136 StatusCallback copy_callback = |
| 134 base::Bind(&CrossOperationDelegate::DidFinishCopy, AsWeakPtr(), | 137 base::Bind(&CrossOperationDelegate::DidFinishCopy, AsWeakPtr(), request); |
| 135 src, callback); | 138 Request copy_request(request.src, request.dest, copy_callback); |
| 136 NewSourceOperation()->CreateSnapshotFile( | 139 NewSourceOperation()->CreateSnapshotFile( |
| 137 src, base::Bind(&CrossOperationDelegate::DidCreateSnapshot, AsWeakPtr(), | 140 request.src, |
| 138 dest, copy_callback)); | 141 base::Bind(&CrossOperationDelegate::DidCreateSnapshot, AsWeakPtr(), |
| 142 copy_request)); |
| 139 } | 143 } |
| 140 | 144 |
| 141 void CrossOperationDelegate::DidCreateSnapshot( | 145 void CrossOperationDelegate::DidCreateSnapshot( |
| 142 const FileSystemURL& dest, | 146 const Request& request, |
| 143 const StatusCallback& callback, | |
| 144 base::PlatformFileError error, | 147 base::PlatformFileError error, |
| 145 const base::PlatformFileInfo& file_info, | 148 const base::PlatformFileInfo& file_info, |
| 146 const base::FilePath& platform_path, | 149 const base::FilePath& platform_path, |
| 147 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | 150 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
| 148 if (error != base::PLATFORM_FILE_OK) { | 151 if (error != base::PLATFORM_FILE_OK) { |
| 149 callback.Run(error); | 152 request.callback.Run(error); |
| 150 return; | 153 return; |
| 151 } | 154 } |
| 152 current_file_ref_ = file_ref; | 155 current_file_ref_ = file_ref; |
| 153 | 156 |
| 154 // For now we assume CreateSnapshotFile always return a valid local file path. | 157 // For now we assume CreateSnapshotFile always return a valid local file path. |
| 155 // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. | 158 // TODO(kinuko): Otherwise create a FileStreamReader to perform a copy/move. |
| 156 DCHECK(!platform_path.empty()); | 159 DCHECK(!platform_path.empty()); |
| 157 | 160 |
| 158 CopyOrMoveFileValidatorFactory* factory = | 161 CopyOrMoveFileValidatorFactory* factory = |
| 159 file_system_context()->GetCopyOrMoveFileValidatorFactory( | 162 file_system_context()->GetCopyOrMoveFileValidatorFactory( |
| 160 dest_root_.type(), &error); | 163 dest_root_.type(), &error); |
| 161 if (error != base::PLATFORM_FILE_OK) { | 164 if (error != base::PLATFORM_FILE_OK) { |
| 162 callback.Run(error); | 165 request.callback.Run(error); |
| 163 return; | 166 return; |
| 164 } | 167 } |
| 165 if (!factory) { | 168 if (!factory) { |
| 166 DidValidateFile(dest, callback, file_info, platform_path, error); | 169 DidValidateFile(request, file_info, platform_path, error); |
| 167 return; | 170 return; |
| 168 } | 171 } |
| 169 | 172 |
| 170 validator_.reset(factory->CreateCopyOrMoveFileValidator(platform_path)); | 173 base::FilePath src_path = request.src.virtual_path(); |
| 174 validator_.reset( |
| 175 factory->CreateCopyOrMoveFileValidator(src_path, platform_path)); |
| 171 validator_->StartValidation( | 176 validator_->StartValidation( |
| 172 base::Bind(&CrossOperationDelegate::DidValidateFile, AsWeakPtr(), | 177 base::Bind(&CrossOperationDelegate::DidValidateFile, AsWeakPtr(), |
| 173 dest, callback, file_info, platform_path)); | 178 request, file_info, platform_path)); |
| 174 } | 179 } |
| 175 | 180 |
| 176 void CrossOperationDelegate::DidValidateFile( | 181 void CrossOperationDelegate::DidValidateFile( |
| 177 const FileSystemURL& dest, | 182 const Request& request, |
| 178 const StatusCallback& callback, | |
| 179 const base::PlatformFileInfo& file_info, | 183 const base::PlatformFileInfo& file_info, |
| 180 const base::FilePath& platform_path, | 184 const base::FilePath& platform_path, |
| 181 base::PlatformFileError error) { | 185 base::PlatformFileError error) { |
| 182 if (error != base::PLATFORM_FILE_OK) { | 186 if (error != base::PLATFORM_FILE_OK) { |
| 183 callback.Run(error); | 187 request.callback.Run(error); |
| 184 return; | 188 return; |
| 185 } | 189 } |
| 186 | 190 |
| 187 NewDestOperation()->CopyInForeignFile(platform_path, dest, callback); | 191 NewDestOperation()->CopyInForeignFile(platform_path, request.dest, |
| 192 request.callback); |
| 188 } | 193 } |
| 189 | 194 |
| 190 void CrossOperationDelegate::DidFinishCopy( | 195 void CrossOperationDelegate::DidFinishCopy( |
| 191 const FileSystemURL& src, | 196 const Request& request, |
| 192 const StatusCallback& callback, | |
| 193 base::PlatformFileError error) { | 197 base::PlatformFileError error) { |
| 194 if (error != base::PLATFORM_FILE_OK || | 198 if (error != base::PLATFORM_FILE_OK || |
| 195 operation_type_ == OPERATION_COPY) { | 199 operation_type_ == OPERATION_COPY) { |
| 196 callback.Run(error); | 200 request.callback.Run(error); |
| 197 return; | 201 return; |
| 198 } | 202 } |
| 199 | 203 |
| 200 DCHECK_EQ(OPERATION_MOVE, operation_type_); | 204 DCHECK_EQ(OPERATION_MOVE, operation_type_); |
| 201 | 205 |
| 202 // Remove the source for finalizing move operation. | 206 // Remove the source for finalizing move operation. |
| 203 NewSourceOperation()->Remove( | 207 NewSourceOperation()->Remove( |
| 204 src, true /* recursive */, | 208 request.src, true /* recursive */, |
| 205 base::Bind(&CrossOperationDelegate::DidRemoveSourceForMove, | 209 base::Bind(&CrossOperationDelegate::DidRemoveSourceForMove, |
| 206 AsWeakPtr(), callback)); | 210 AsWeakPtr(), request)); |
| 207 } | 211 } |
| 208 | 212 |
| 209 void CrossOperationDelegate::DidRemoveSourceForMove( | 213 void CrossOperationDelegate::DidRemoveSourceForMove( |
| 210 const StatusCallback& callback, | 214 const Request& request, |
| 211 base::PlatformFileError error) { | 215 base::PlatformFileError error) { |
| 212 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 216 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
| 213 error = base::PLATFORM_FILE_OK; | 217 error = base::PLATFORM_FILE_OK; |
| 214 callback.Run(error); | 218 request.callback.Run(error); |
| 215 } | 219 } |
| 216 | 220 |
| 217 FileSystemURL CrossOperationDelegate::CreateDestURL( | 221 FileSystemURL CrossOperationDelegate::CreateDestURL( |
| 218 const FileSystemURL& src_url) const { | 222 const FileSystemURL& src_url) const { |
| 219 DCHECK_EQ(src_root_.type(), src_url.type()); | 223 DCHECK_EQ(src_root_.type(), src_url.type()); |
| 220 DCHECK_EQ(src_root_.origin(), src_url.origin()); | 224 DCHECK_EQ(src_root_.origin(), src_url.origin()); |
| 221 | 225 |
| 222 base::FilePath relative = dest_root_.virtual_path(); | 226 base::FilePath relative = dest_root_.virtual_path(); |
| 223 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), | 227 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), |
| 224 &relative); | 228 &relative); |
| 225 return file_system_context()->CreateCrackedFileSystemURL( | 229 return file_system_context()->CreateCrackedFileSystemURL( |
| 226 dest_root_.origin(), | 230 dest_root_.origin(), |
| 227 dest_root_.mount_type(), | 231 dest_root_.mount_type(), |
| 228 relative); | 232 relative); |
| 229 } | 233 } |
| 230 | 234 |
| 231 LocalFileSystemOperation* CrossOperationDelegate::NewDestOperation() { | 235 LocalFileSystemOperation* CrossOperationDelegate::NewDestOperation() { |
| 232 return NewNestedOperation(); | 236 return NewNestedOperation(); |
| 233 } | 237 } |
| 234 | 238 |
| 235 LocalFileSystemOperation* CrossOperationDelegate::NewSourceOperation() { | 239 LocalFileSystemOperation* CrossOperationDelegate::NewSourceOperation() { |
| 236 if (same_file_system_) | 240 if (same_file_system_) |
| 237 return NewDestOperation(); | 241 return NewDestOperation(); |
| 238 return src_root_operation_->CreateNestedOperation(); | 242 return src_root_operation_->CreateNestedOperation(); |
| 239 } | 243 } |
| 240 | 244 |
| 241 } // namespace fileapi | 245 } // namespace fileapi |
| OLD | NEW |