| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_operation.h" | 5 #include "webkit/fileapi/file_system_operation.h" |
| 6 | 6 |
| 7 #include "base/time.h" | 7 #include "base/time.h" |
| 8 #include "net/url_request/url_request_context.h" | 8 #include "net/url_request/url_request_context.h" |
| 9 #include "webkit/fileapi/file_system_callback_dispatcher.h" | 9 #include "webkit/fileapi/file_system_callback_dispatcher.h" |
| 10 #include "webkit/fileapi/file_writer_delegate.h" | 10 #include "webkit/fileapi/file_writer_delegate.h" |
| 11 | 11 |
| 12 namespace fileapi { | 12 namespace fileapi { |
| 13 | 13 |
| 14 FileSystemOperation::FileSystemOperation( | 14 FileSystemOperation::FileSystemOperation( |
| 15 FileSystemCallbackDispatcher* dispatcher, | 15 FileSystemCallbackDispatcher* dispatcher, |
| 16 scoped_refptr<base::MessageLoopProxy> proxy) | 16 scoped_refptr<base::MessageLoopProxy> proxy) |
| 17 : proxy_(proxy), | 17 : proxy_(proxy), |
| 18 dispatcher_(dispatcher), | 18 dispatcher_(dispatcher), |
| 19 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 19 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 20 cancel_operation_(NULL) { | |
| 21 DCHECK(dispatcher); | 20 DCHECK(dispatcher); |
| 22 #ifndef NDEBUG | 21 #ifndef NDEBUG |
| 23 pending_operation_ = kOperationNone; | 22 pending_operation_ = kOperationNone; |
| 24 #endif | 23 #endif |
| 25 } | 24 } |
| 26 | 25 |
| 27 FileSystemOperation::~FileSystemOperation() { | 26 FileSystemOperation::~FileSystemOperation() { |
| 28 if (file_writer_delegate_.get()) | 27 if (file_writer_delegate_.get()) |
| 29 base::FileUtilProxy::Close(proxy_, file_writer_delegate_->file(), NULL); | 28 base::FileUtilProxy::Close(proxy_, file_writer_delegate_->file(), NULL); |
| 30 } | 29 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 callback_factory_.NewCallback( | 151 callback_factory_.NewCallback( |
| 153 &FileSystemOperation::OnFileOpenedForWrite)); | 152 &FileSystemOperation::OnFileOpenedForWrite)); |
| 154 } | 153 } |
| 155 | 154 |
| 156 void FileSystemOperation::OnFileOpenedForWrite( | 155 void FileSystemOperation::OnFileOpenedForWrite( |
| 157 base::PlatformFileError rv, | 156 base::PlatformFileError rv, |
| 158 base::PassPlatformFile file, | 157 base::PassPlatformFile file, |
| 159 bool created) { | 158 bool created) { |
| 160 if (base::PLATFORM_FILE_OK != rv) { | 159 if (base::PLATFORM_FILE_OK != rv) { |
| 161 dispatcher_->DidFail(rv); | 160 dispatcher_->DidFail(rv); |
| 161 delete this; |
| 162 return; | 162 return; |
| 163 } | 163 } |
| 164 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); | 164 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); |
| 165 } | 165 } |
| 166 | 166 |
| 167 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { | 167 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { |
| 168 #ifndef NDEBUG | 168 #ifndef NDEBUG |
| 169 DCHECK(kOperationNone == pending_operation_); | 169 DCHECK(kOperationNone == pending_operation_); |
| 170 pending_operation_ = kOperationTruncate; | 170 pending_operation_ = kOperationTruncate; |
| 171 #endif | 171 #endif |
| (...skipping 10 matching lines...) Expand all Loading... |
| 182 pending_operation_ = kOperationTouchFile; | 182 pending_operation_ = kOperationTouchFile; |
| 183 #endif | 183 #endif |
| 184 | 184 |
| 185 base::FileUtilProxy::Touch( | 185 base::FileUtilProxy::Touch( |
| 186 proxy_, path, last_access_time, last_modified_time, | 186 proxy_, path, last_access_time, last_modified_time, |
| 187 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); | 187 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); |
| 188 } | 188 } |
| 189 | 189 |
| 190 // We can only get here on a write or truncate that's not yet completed. | 190 // We can only get here on a write or truncate that's not yet completed. |
| 191 // We don't support cancelling any other operation at this time. | 191 // We don't support cancelling any other operation at this time. |
| 192 void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation) { | 192 void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation_ptr) { |
| 193 scoped_ptr<FileSystemOperation> cancel_operation(cancel_operation_ptr); |
| 193 if (file_writer_delegate_.get()) { | 194 if (file_writer_delegate_.get()) { |
| 194 #ifndef NDEBUG | 195 #ifndef NDEBUG |
| 195 DCHECK(kOperationWrite == pending_operation_); | 196 DCHECK(kOperationWrite == pending_operation_); |
| 196 #endif | 197 #endif |
| 197 // Writes are done without proxying through FileUtilProxy after the initial | 198 // Writes are done without proxying through FileUtilProxy after the initial |
| 198 // opening of the PlatformFile. All state changes are done on this thread, | 199 // opening of the PlatformFile. All state changes are done on this thread, |
| 199 // so we're guaranteed to be able to shut down atomically. We do need to | 200 // so we're guaranteed to be able to shut down atomically. We do need to |
| 200 // check that the file has been opened [which means the blob_request_ has | 201 // check that the file has been opened [which means the blob_request_ has |
| 201 // been created], so we know how much we need to do. | 202 // been created], so we know how much we need to do. |
| 202 if (blob_request_.get()) | 203 if (blob_request_.get()) |
| 203 // This halts any calls to file_writer_delegate_ from blob_request_. | 204 // This halts any calls to file_writer_delegate_ from blob_request_. |
| 204 blob_request_->Cancel(); | 205 blob_request_->Cancel(); |
| 205 | 206 |
| 206 // This deletes us, and by proxy deletes file_writer_delegate_ if any. | |
| 207 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 207 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
| 208 cancel_operation->dispatcher_->DidSucceed(); | 208 cancel_operation->dispatcher()->DidSucceed(); |
| 209 delete this; |
| 209 } else { | 210 } else { |
| 210 #ifndef NDEBUG | 211 #ifndef NDEBUG |
| 211 DCHECK(kOperationTruncate == pending_operation_); | 212 DCHECK(kOperationTruncate == pending_operation_); |
| 212 #endif | 213 #endif |
| 213 // We're cancelling a truncate operation, but we can't actually stop it | 214 // We're cancelling a truncate operation, but we can't actually stop it |
| 214 // since it's been proxied to another thread. We need to save the | 215 // since it's been proxied to another thread. We need to save the |
| 215 // cancel_operation so that when the truncate returns, it can see that it's | 216 // cancel_operation so that when the truncate returns, it can see that it's |
| 216 // been cancelled, report it, and report that the cancel has succeeded. | 217 // been cancelled, report it, and report that the cancel has succeeded. |
| 217 cancel_operation_ = cancel_operation; | 218 DCHECK(!cancel_operation_.get()); |
| 219 cancel_operation_.swap(cancel_operation); |
| 218 } | 220 } |
| 219 } | 221 } |
| 220 | 222 |
| 221 void FileSystemOperation::DidEnsureFileExistsExclusive( | 223 void FileSystemOperation::DidEnsureFileExistsExclusive( |
| 222 base::PlatformFileError rv, bool created) { | 224 base::PlatformFileError rv, bool created) { |
| 223 if (rv == base::PLATFORM_FILE_OK && !created) | 225 if (rv == base::PLATFORM_FILE_OK && !created) { |
| 224 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); | 226 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); |
| 225 else | 227 delete this; |
| 228 } else |
| 226 DidFinishFileOperation(rv); | 229 DidFinishFileOperation(rv); |
| 227 } | 230 } |
| 228 | 231 |
| 229 void FileSystemOperation::DidEnsureFileExistsNonExclusive( | 232 void FileSystemOperation::DidEnsureFileExistsNonExclusive( |
| 230 base::PlatformFileError rv, bool /* created */) { | 233 base::PlatformFileError rv, bool /* created */) { |
| 231 DidFinishFileOperation(rv); | 234 DidFinishFileOperation(rv); |
| 232 } | 235 } |
| 233 | 236 |
| 234 void FileSystemOperation::DidFinishFileOperation( | 237 void FileSystemOperation::DidFinishFileOperation( |
| 235 base::PlatformFileError rv) { | 238 base::PlatformFileError rv) { |
| 236 if (cancel_operation_) { | 239 if (cancel_operation_.get()) { |
| 237 #ifndef NDEBUG | 240 #ifndef NDEBUG |
| 238 DCHECK(kOperationTruncate == pending_operation_); | 241 DCHECK(kOperationTruncate == pending_operation_); |
| 239 #endif | 242 #endif |
| 240 FileSystemOperation *cancel_op = cancel_operation_; | 243 |
| 241 // This call deletes us, so we have to extract cancel_op first. | |
| 242 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 244 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
| 243 cancel_op->dispatcher_->DidSucceed(); | 245 cancel_operation_->dispatcher()->DidSucceed(); |
| 244 } else if (rv == base::PLATFORM_FILE_OK) { | 246 } else if (rv == base::PLATFORM_FILE_OK) { |
| 245 dispatcher_->DidSucceed(); | 247 dispatcher_->DidSucceed(); |
| 246 } else { | 248 } else { |
| 247 dispatcher_->DidFail(rv); | 249 dispatcher_->DidFail(rv); |
| 248 } | 250 } |
| 251 delete this; |
| 249 } | 252 } |
| 250 | 253 |
| 251 void FileSystemOperation::DidDirectoryExists( | 254 void FileSystemOperation::DidDirectoryExists( |
| 252 base::PlatformFileError rv, | 255 base::PlatformFileError rv, |
| 253 const base::PlatformFileInfo& file_info) { | 256 const base::PlatformFileInfo& file_info) { |
| 254 if (rv == base::PLATFORM_FILE_OK) { | 257 if (rv == base::PLATFORM_FILE_OK) { |
| 255 if (file_info.is_directory) | 258 if (file_info.is_directory) |
| 256 dispatcher_->DidSucceed(); | 259 dispatcher_->DidSucceed(); |
| 257 else | 260 else |
| 258 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 261 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 259 } else { | 262 } else { |
| 260 dispatcher_->DidFail(rv); | 263 dispatcher_->DidFail(rv); |
| 261 } | 264 } |
| 265 delete this; |
| 262 } | 266 } |
| 263 | 267 |
| 264 void FileSystemOperation::DidFileExists( | 268 void FileSystemOperation::DidFileExists( |
| 265 base::PlatformFileError rv, | 269 base::PlatformFileError rv, |
| 266 const base::PlatformFileInfo& file_info) { | 270 const base::PlatformFileInfo& file_info) { |
| 267 if (rv == base::PLATFORM_FILE_OK) { | 271 if (rv == base::PLATFORM_FILE_OK) { |
| 268 if (file_info.is_directory) | 272 if (file_info.is_directory) |
| 269 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 273 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 270 else | 274 else |
| 271 dispatcher_->DidSucceed(); | 275 dispatcher_->DidSucceed(); |
| 272 } else { | 276 } else { |
| 273 dispatcher_->DidFail(rv); | 277 dispatcher_->DidFail(rv); |
| 274 } | 278 } |
| 279 delete this; |
| 275 } | 280 } |
| 276 | 281 |
| 277 void FileSystemOperation::DidGetMetadata( | 282 void FileSystemOperation::DidGetMetadata( |
| 278 base::PlatformFileError rv, | 283 base::PlatformFileError rv, |
| 279 const base::PlatformFileInfo& file_info) { | 284 const base::PlatformFileInfo& file_info) { |
| 280 if (rv == base::PLATFORM_FILE_OK) | 285 if (rv == base::PLATFORM_FILE_OK) |
| 281 dispatcher_->DidReadMetadata(file_info); | 286 dispatcher_->DidReadMetadata(file_info); |
| 282 else | 287 else |
| 283 dispatcher_->DidFail(rv); | 288 dispatcher_->DidFail(rv); |
| 289 delete this; |
| 284 } | 290 } |
| 285 | 291 |
| 286 void FileSystemOperation::DidReadDirectory( | 292 void FileSystemOperation::DidReadDirectory( |
| 287 base::PlatformFileError rv, | 293 base::PlatformFileError rv, |
| 288 const std::vector<base::FileUtilProxy::Entry>& entries) { | 294 const std::vector<base::FileUtilProxy::Entry>& entries) { |
| 289 if (rv == base::PLATFORM_FILE_OK) | 295 if (rv == base::PLATFORM_FILE_OK) |
| 290 dispatcher_->DidReadDirectory(entries, false /* has_more */); | 296 dispatcher_->DidReadDirectory(entries, false /* has_more */); |
| 291 else | 297 else |
| 292 dispatcher_->DidFail(rv); | 298 dispatcher_->DidFail(rv); |
| 299 delete this; |
| 293 } | 300 } |
| 294 | 301 |
| 295 void FileSystemOperation::DidWrite( | 302 void FileSystemOperation::DidWrite( |
| 296 base::PlatformFileError rv, | 303 base::PlatformFileError rv, |
| 297 int64 bytes, | 304 int64 bytes, |
| 298 bool complete) { | 305 bool complete) { |
| 299 if (rv == base::PLATFORM_FILE_OK) | 306 if (rv == base::PLATFORM_FILE_OK) |
| 300 dispatcher_->DidWrite(bytes, complete); | 307 dispatcher_->DidWrite(bytes, complete); |
| 301 else | 308 else |
| 302 dispatcher_->DidFail(rv); | 309 dispatcher_->DidFail(rv); |
| 310 if (complete || rv != base::PLATFORM_FILE_OK) |
| 311 delete this; |
| 303 } | 312 } |
| 304 | 313 |
| 305 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { | 314 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { |
| 306 if (rv == base::PLATFORM_FILE_OK) | 315 if (rv == base::PLATFORM_FILE_OK) |
| 307 dispatcher_->DidSucceed(); | 316 dispatcher_->DidSucceed(); |
| 308 else | 317 else |
| 309 dispatcher_->DidFail(rv); | 318 dispatcher_->DidFail(rv); |
| 319 delete this; |
| 310 } | 320 } |
| 311 | 321 |
| 312 } // namespace fileapi | 322 } // namespace fileapi |
| OLD | NEW |