| 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_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_system_context.h" | 10 #include "webkit/fileapi/file_system_context.h" |
| 11 #include "webkit/fileapi/file_system_path_manager.h" | 11 #include "webkit/fileapi/file_system_path_manager.h" |
| 12 #include "webkit/fileapi/file_system_quota_manager.h" | |
| 13 #include "webkit/fileapi/file_writer_delegate.h" | 12 #include "webkit/fileapi/file_writer_delegate.h" |
| 14 | 13 |
| 15 namespace fileapi { | 14 namespace fileapi { |
| 16 | 15 |
| 17 FileSystemOperation::FileSystemOperation( | 16 FileSystemOperation::FileSystemOperation( |
| 18 FileSystemCallbackDispatcher* dispatcher, | 17 FileSystemCallbackDispatcher* dispatcher, |
| 19 scoped_refptr<base::MessageLoopProxy> proxy, | 18 scoped_refptr<base::MessageLoopProxy> proxy, |
| 20 FileSystemContext* file_system_context) | 19 FileSystemContext* file_system_context) |
| 21 : proxy_(proxy), | 20 : proxy_(proxy), |
| 22 dispatcher_(dispatcher), | 21 dispatcher_(dispatcher), |
| (...skipping 24 matching lines...) Expand all Loading... |
| 47 callback_factory_.NewCallback(&FileSystemOperation::DidGetRootPath)); | 46 callback_factory_.NewCallback(&FileSystemOperation::DidGetRootPath)); |
| 48 } | 47 } |
| 49 | 48 |
| 50 void FileSystemOperation::CreateFile(const FilePath& path, | 49 void FileSystemOperation::CreateFile(const FilePath& path, |
| 51 bool exclusive) { | 50 bool exclusive) { |
| 52 #ifndef NDEBUG | 51 #ifndef NDEBUG |
| 53 DCHECK(kOperationNone == pending_operation_); | 52 DCHECK(kOperationNone == pending_operation_); |
| 54 pending_operation_ = kOperationCreateFile; | 53 pending_operation_ = kOperationCreateFile; |
| 55 #endif | 54 #endif |
| 56 | 55 |
| 57 if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) { | 56 if (!VerifyFileSystemPathForWrite(path, true /* create */)) { |
| 58 delete this; | 57 delete this; |
| 59 return; | 58 return; |
| 60 } | 59 } |
| 61 base::FileUtilProxy::EnsureFileExists( | 60 base::FileUtilProxy::EnsureFileExists( |
| 62 proxy_, path, callback_factory_.NewCallback( | 61 proxy_, path, callback_factory_.NewCallback( |
| 63 exclusive ? &FileSystemOperation::DidEnsureFileExistsExclusive | 62 exclusive ? &FileSystemOperation::DidEnsureFileExistsExclusive |
| 64 : &FileSystemOperation::DidEnsureFileExistsNonExclusive)); | 63 : &FileSystemOperation::DidEnsureFileExistsNonExclusive)); |
| 65 } | 64 } |
| 66 | 65 |
| 67 void FileSystemOperation::CreateDirectory(const FilePath& path, | 66 void FileSystemOperation::CreateDirectory(const FilePath& path, |
| 68 bool exclusive, | 67 bool exclusive, |
| 69 bool recursive) { | 68 bool recursive) { |
| 70 #ifndef NDEBUG | 69 #ifndef NDEBUG |
| 71 DCHECK(kOperationNone == pending_operation_); | 70 DCHECK(kOperationNone == pending_operation_); |
| 72 pending_operation_ = kOperationCreateDirectory; | 71 pending_operation_ = kOperationCreateDirectory; |
| 73 #endif | 72 #endif |
| 74 | 73 |
| 75 if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) { | 74 if (!VerifyFileSystemPathForWrite(path, true /* create */)) { |
| 76 delete this; | 75 delete this; |
| 77 return; | 76 return; |
| 78 } | 77 } |
| 79 base::FileUtilProxy::CreateDirectory( | 78 base::FileUtilProxy::CreateDirectory( |
| 80 proxy_, path, exclusive, recursive, callback_factory_.NewCallback( | 79 proxy_, path, exclusive, recursive, callback_factory_.NewCallback( |
| 81 &FileSystemOperation::DidFinishFileOperation)); | 80 &FileSystemOperation::DidFinishFileOperation)); |
| 82 } | 81 } |
| 83 | 82 |
| 84 void FileSystemOperation::Copy(const FilePath& src_path, | 83 void FileSystemOperation::Copy(const FilePath& src_path, |
| 85 const FilePath& dest_path) { | 84 const FilePath& dest_path) { |
| 86 #ifndef NDEBUG | 85 #ifndef NDEBUG |
| 87 DCHECK(kOperationNone == pending_operation_); | 86 DCHECK(kOperationNone == pending_operation_); |
| 88 pending_operation_ = kOperationCopy; | 87 pending_operation_ = kOperationCopy; |
| 89 #endif | 88 #endif |
| 90 | 89 |
| 91 if (!VerifyFileSystemPathForRead(src_path) || | 90 if (!VerifyFileSystemPathForRead(src_path) || |
| 92 !VerifyFileSystemPathForWrite(dest_path, true /* create */, | 91 !VerifyFileSystemPathForWrite(dest_path, true /* create */)) { |
| 93 FileSystemQuotaManager::kUnknownSize)) { | |
| 94 delete this; | 92 delete this; |
| 95 return; | 93 return; |
| 96 } | 94 } |
| 97 base::FileUtilProxy::Copy(proxy_, src_path, dest_path, | 95 base::FileUtilProxy::Copy(proxy_, src_path, dest_path, |
| 98 callback_factory_.NewCallback( | 96 callback_factory_.NewCallback( |
| 99 &FileSystemOperation::DidFinishFileOperation)); | 97 &FileSystemOperation::DidFinishFileOperation)); |
| 100 } | 98 } |
| 101 | 99 |
| 102 void FileSystemOperation::Move(const FilePath& src_path, | 100 void FileSystemOperation::Move(const FilePath& src_path, |
| 103 const FilePath& dest_path) { | 101 const FilePath& dest_path) { |
| 104 #ifndef NDEBUG | 102 #ifndef NDEBUG |
| 105 DCHECK(kOperationNone == pending_operation_); | 103 DCHECK(kOperationNone == pending_operation_); |
| 106 pending_operation_ = kOperationMove; | 104 pending_operation_ = kOperationMove; |
| 107 #endif | 105 #endif |
| 108 | 106 |
| 109 if (!VerifyFileSystemPathForRead(src_path) || | 107 if (!VerifyFileSystemPathForRead(src_path) || |
| 110 !VerifyFileSystemPathForWrite(dest_path, true /* create */, | 108 !VerifyFileSystemPathForWrite(dest_path, true /* create */)) { |
| 111 FileSystemQuotaManager::kUnknownSize)) { | |
| 112 delete this; | 109 delete this; |
| 113 return; | 110 return; |
| 114 } | 111 } |
| 115 base::FileUtilProxy::Move(proxy_, src_path, dest_path, | 112 base::FileUtilProxy::Move(proxy_, src_path, dest_path, |
| 116 callback_factory_.NewCallback( | 113 callback_factory_.NewCallback( |
| 117 &FileSystemOperation::DidFinishFileOperation)); | 114 &FileSystemOperation::DidFinishFileOperation)); |
| 118 } | 115 } |
| 119 | 116 |
| 120 void FileSystemOperation::DirectoryExists(const FilePath& path) { | 117 void FileSystemOperation::DirectoryExists(const FilePath& path) { |
| 121 #ifndef NDEBUG | 118 #ifndef NDEBUG |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 callback_factory_.NewCallback( | 170 callback_factory_.NewCallback( |
| 174 &FileSystemOperation::DidReadDirectory)); | 171 &FileSystemOperation::DidReadDirectory)); |
| 175 } | 172 } |
| 176 | 173 |
| 177 void FileSystemOperation::Remove(const FilePath& path, bool recursive) { | 174 void FileSystemOperation::Remove(const FilePath& path, bool recursive) { |
| 178 #ifndef NDEBUG | 175 #ifndef NDEBUG |
| 179 DCHECK(kOperationNone == pending_operation_); | 176 DCHECK(kOperationNone == pending_operation_); |
| 180 pending_operation_ = kOperationRemove; | 177 pending_operation_ = kOperationRemove; |
| 181 #endif | 178 #endif |
| 182 | 179 |
| 183 if (!VerifyFileSystemPathForWrite(path, false /* create */, 0)) { | 180 if (!VerifyFileSystemPathForWrite(path, false /* create */)) { |
| 184 delete this; | 181 delete this; |
| 185 return; | 182 return; |
| 186 } | 183 } |
| 187 base::FileUtilProxy::Delete(proxy_, path, recursive, | 184 base::FileUtilProxy::Delete(proxy_, path, recursive, |
| 188 callback_factory_.NewCallback( | 185 callback_factory_.NewCallback( |
| 189 &FileSystemOperation::DidFinishFileOperation)); | 186 &FileSystemOperation::DidFinishFileOperation)); |
| 190 } | 187 } |
| 191 | 188 |
| 192 void FileSystemOperation::Write( | 189 void FileSystemOperation::Write( |
| 193 scoped_refptr<net::URLRequestContext> url_request_context, | 190 scoped_refptr<net::URLRequestContext> url_request_context, |
| 194 const FilePath& path, | 191 const FilePath& path, |
| 195 const GURL& blob_url, | 192 const GURL& blob_url, |
| 196 int64 offset) { | 193 int64 offset) { |
| 197 #ifndef NDEBUG | 194 #ifndef NDEBUG |
| 198 DCHECK(kOperationNone == pending_operation_); | 195 DCHECK(kOperationNone == pending_operation_); |
| 199 pending_operation_ = kOperationWrite; | 196 pending_operation_ = kOperationWrite; |
| 200 #endif | 197 #endif |
| 201 if (!VerifyFileSystemPathForWrite(path, true /* create */, | 198 if (!VerifyFileSystemPathForWrite(path, true /* create */)) { |
| 202 FileSystemQuotaManager::kUnknownSize)) { | |
| 203 delete this; | 199 delete this; |
| 204 return; | 200 return; |
| 205 } | 201 } |
| 206 DCHECK(blob_url.is_valid()); | 202 DCHECK(blob_url.is_valid()); |
| 207 file_writer_delegate_.reset(new FileWriterDelegate(this, offset)); | 203 file_writer_delegate_.reset(new FileWriterDelegate(this, offset)); |
| 208 blob_request_.reset( | 204 blob_request_.reset( |
| 209 new net::URLRequest(blob_url, file_writer_delegate_.get())); | 205 new net::URLRequest(blob_url, file_writer_delegate_.get())); |
| 210 blob_request_->set_context(url_request_context); | 206 blob_request_->set_context(url_request_context); |
| 211 base::FileUtilProxy::CreateOrOpen( | 207 base::FileUtilProxy::CreateOrOpen( |
| 212 proxy_, | 208 proxy_, |
| 213 path, | 209 path, |
| 214 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | | 210 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | |
| 215 base::PLATFORM_FILE_ASYNC, | 211 base::PLATFORM_FILE_ASYNC, |
| 216 callback_factory_.NewCallback( | 212 callback_factory_.NewCallback( |
| 217 &FileSystemOperation::OnFileOpenedForWrite)); | 213 &FileSystemOperation::OnFileOpenedForWrite)); |
| 218 } | 214 } |
| 219 | 215 |
| 220 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { | 216 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { |
| 221 #ifndef NDEBUG | 217 #ifndef NDEBUG |
| 222 DCHECK(kOperationNone == pending_operation_); | 218 DCHECK(kOperationNone == pending_operation_); |
| 223 pending_operation_ = kOperationTruncate; | 219 pending_operation_ = kOperationTruncate; |
| 224 #endif | 220 #endif |
| 225 if (!VerifyFileSystemPathForWrite(path, false /* create */, 0)) { | 221 if (!VerifyFileSystemPathForWrite(path, false /* create */)) { |
| 226 delete this; | 222 delete this; |
| 227 return; | 223 return; |
| 228 } | 224 } |
| 229 base::FileUtilProxy::Truncate(proxy_, path, length, | 225 base::FileUtilProxy::Truncate(proxy_, path, length, |
| 230 callback_factory_.NewCallback( | 226 callback_factory_.NewCallback( |
| 231 &FileSystemOperation::DidFinishFileOperation)); | 227 &FileSystemOperation::DidFinishFileOperation)); |
| 232 } | 228 } |
| 233 | 229 |
| 234 void FileSystemOperation::TouchFile(const FilePath& path, | 230 void FileSystemOperation::TouchFile(const FilePath& path, |
| 235 const base::Time& last_access_time, | 231 const base::Time& last_access_time, |
| 236 const base::Time& last_modified_time) { | 232 const base::Time& last_modified_time) { |
| 237 #ifndef NDEBUG | 233 #ifndef NDEBUG |
| 238 DCHECK(kOperationNone == pending_operation_); | 234 DCHECK(kOperationNone == pending_operation_); |
| 239 pending_operation_ = kOperationTouchFile; | 235 pending_operation_ = kOperationTouchFile; |
| 240 #endif | 236 #endif |
| 241 | 237 |
| 242 if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) { | 238 if (!VerifyFileSystemPathForWrite(path, true /* create */)) { |
| 243 delete this; | 239 delete this; |
| 244 return; | 240 return; |
| 245 } | 241 } |
| 246 base::FileUtilProxy::Touch( | 242 base::FileUtilProxy::Touch( |
| 247 proxy_, path, last_access_time, last_modified_time, | 243 proxy_, path, last_access_time, last_modified_time, |
| 248 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); | 244 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); |
| 249 } | 245 } |
| 250 | 246 |
| 251 // We can only get here on a write or truncate that's not yet completed. | 247 // We can only get here on a write or truncate that's not yet completed. |
| 252 // We don't support cancelling any other operation at this time. | 248 // We don't support cancelling any other operation at this time. |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 // |path| is under the valid FileSystem root path for this host context. | 405 // |path| is under the valid FileSystem root path for this host context. |
| 410 if (!file_system_context_->path_manager()->CrackFileSystemPath( | 406 if (!file_system_context_->path_manager()->CrackFileSystemPath( |
| 411 path, NULL, NULL, NULL)) { | 407 path, NULL, NULL, NULL)) { |
| 412 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); | 408 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); |
| 413 return false; | 409 return false; |
| 414 } | 410 } |
| 415 return true; | 411 return true; |
| 416 } | 412 } |
| 417 | 413 |
| 418 bool FileSystemOperation::VerifyFileSystemPathForWrite( | 414 bool FileSystemOperation::VerifyFileSystemPathForWrite( |
| 419 const FilePath& path, bool create, int64 growth) { | 415 const FilePath& path, bool create) { |
| 420 GURL origin_url; | 416 GURL origin_url; |
| 421 FilePath virtual_path; | 417 FilePath virtual_path; |
| 422 | 418 |
| 423 // If we have no context, we just allow any operations. | 419 // If we have no context, we just allow any operations. |
| 424 if (!file_system_context_.get()) | 420 if (!file_system_context_.get()) |
| 425 return true; | 421 return true; |
| 426 | 422 |
| 427 if (!file_system_context_->path_manager()->CrackFileSystemPath( | 423 if (!file_system_context_->path_manager()->CrackFileSystemPath( |
| 428 path, &origin_url, NULL, &virtual_path)) { | 424 path, &origin_url, NULL, &virtual_path)) { |
| 429 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); | 425 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); |
| 430 return false; | 426 return false; |
| 431 } | 427 } |
| 432 // Any write access is disallowed on the root path. | 428 // Any write access is disallowed on the root path. |
| 433 if (virtual_path.value().length() == 0 || | 429 if (virtual_path.value().length() == 0 || |
| 434 virtual_path.DirName().value() == virtual_path.value()) { | 430 virtual_path.DirName().value() == virtual_path.value()) { |
| 435 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); | 431 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); |
| 436 return false; | 432 return false; |
| 437 } | 433 } |
| 438 if (create && FileSystemPathManager::IsRestrictedFileName( | 434 if (create && FileSystemPathManager::IsRestrictedFileName( |
| 439 path.BaseName())) { | 435 path.BaseName())) { |
| 440 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); | 436 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); |
| 441 return false; | 437 return false; |
| 442 } | 438 } |
| 443 // TODO(kinuko): For operations with kUnknownSize we'll eventually | 439 // TODO(kinuko): the check must be moved to QuotaFileSystemFileUtil. |
| 444 // need to resolve what amount of size it's going to write. | 440 if (!file_system_context_->IsStorageUnlimited(origin_url)) { |
| 445 if (!file_system_context_->quota_manager()->CheckOriginQuota( | |
| 446 origin_url, growth)) { | |
| 447 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 441 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 448 return false; | 442 return false; |
| 449 } | 443 } |
| 450 return true; | 444 return true; |
| 451 } | 445 } |
| 452 | 446 |
| 453 } // namespace fileapi | 447 } // namespace fileapi |
| OLD | NEW |