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 3 // found in the LICENSE file. 4 5 #include "webkit/browser/fileapi/async_file_util_adapter.h" 6 7 #include "base/bind.h" 8 #include "base/sequenced_task_runner.h" 9 #include "base/task_runner_util.h" 10 #include "webkit/browser/fileapi/file_system_context.h" 11 #include "webkit/browser/fileapi/file_system_file_util.h" 12 #include "webkit/browser/fileapi/file_system_operation_context.h" 13 #include "webkit/browser/fileapi/file_system_url.h" 14 #include "webkit/common/blob/shareable_file_reference.h" 15 #include "webkit/common/fileapi/file_system_util.h" 16 17 using base::Bind; 18 using base::Callback; 19 using base::Owned; 20 using base::PlatformFileError; 21 using base::Unretained; 22 using webkit_blob::ShareableFileReference; 23 24 namespace fileapi { 25 26 namespace { 27 28 class EnsureFileExistsHelper { 29 public: 30 EnsureFileExistsHelper() : error_(base::PLATFORM_FILE_OK), created_(false) {} 31 32 void RunWork(FileSystemFileUtil* file_util, 33 FileSystemOperationContext* context, 34 const FileSystemURL& url) { 35 error_ = file_util->EnsureFileExists(context, url, &created_); 36 } 37 38 void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) { 39 callback.Run(error_, created_); 40 } 41 42 private: 43 base::PlatformFileError error_; 44 bool created_; 45 DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper); 46 }; 47 48 class GetFileInfoHelper { 49 public: 50 GetFileInfoHelper() 51 : error_(base::PLATFORM_FILE_OK) {} 52 53 void GetFileInfo(FileSystemFileUtil* file_util, 54 FileSystemOperationContext* context, 55 const FileSystemURL& url) { 56 error_ = file_util->GetFileInfo(context, url, &file_info_, &platform_path_); 57 } 58 59 void CreateSnapshotFile(FileSystemFileUtil* file_util, 60 FileSystemOperationContext* context, 61 const FileSystemURL& url) { 62 scoped_file_ = file_util->CreateSnapshotFile( 63 context, url, &error_, &file_info_, &platform_path_); 64 } 65 66 void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) { 67 callback.Run(error_, file_info_); 68 } 69 70 void ReplySnapshotFile( 71 const AsyncFileUtil::CreateSnapshotFileCallback& callback) { 72 callback.Run(error_, file_info_, platform_path_, 73 ShareableFileReference::GetOrCreate(scoped_file_.Pass())); 74 } 75 76 private: 77 base::PlatformFileError error_; 78 base::PlatformFileInfo file_info_; 79 base::FilePath platform_path_; 80 webkit_blob::ScopedFile scoped_file_; 81 DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper); 82 }; 83 84 class ReadDirectoryHelper { 85 public: 86 ReadDirectoryHelper() : error_(base::PLATFORM_FILE_OK) {} 87 88 void RunWork(FileSystemFileUtil* file_util, 89 FileSystemOperationContext* context, 90 const FileSystemURL& url) { 91 base::PlatformFileInfo file_info; 92 base::FilePath platform_path; 93 PlatformFileError error = file_util->GetFileInfo( 94 context, url, &file_info, &platform_path); 95 if (error != base::PLATFORM_FILE_OK) { 96 error_ = error; 97 return; 98 } 99 if (!file_info.is_directory) { 100 error_ = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; 101 return; 102 } 103 104 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum( 105 file_util->CreateFileEnumerator(context, url)); 106 107 base::FilePath current; 108 while (!(current = file_enum->Next()).empty()) { 109 DirectoryEntry entry; 110 entry.is_directory = file_enum->IsDirectory(); 111 entry.name = VirtualPath::BaseName(current).value(); 112 entry.size = file_enum->Size(); 113 entry.last_modified_time = file_enum->LastModifiedTime(); 114 entries_.push_back(entry); 115 } 116 error_ = base::PLATFORM_FILE_OK; 117 } 118 119 void Reply(const AsyncFileUtil::ReadDirectoryCallback& callback) { 120 callback.Run(error_, entries_, false /* has_more */); 121 } 122 123 private: 124 base::PlatformFileError error_; 125 std::vector<DirectoryEntry> entries_; 126 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryHelper); 127 }; 128 129 void RunCreateOrOpenCallback( 130 const AsyncFileUtil::CreateOrOpenCallback& callback, 131 base::PlatformFileError result, 132 base::PassPlatformFile file, 133 bool created) { 134 callback.Run(result, file, base::Closure()); 135 } 136 137 } // namespace 138 139 AsyncFileUtilAdapter::AsyncFileUtilAdapter( 140 FileSystemFileUtil* sync_file_util) 141 : sync_file_util_(sync_file_util) { 142 DCHECK(sync_file_util_.get()); 143 } 144 145 AsyncFileUtilAdapter::~AsyncFileUtilAdapter() { 146 } 147 148 void AsyncFileUtilAdapter::CreateOrOpen( 149 scoped_ptr<FileSystemOperationContext> context, 150 const FileSystemURL& url, 151 int file_flags, 152 const CreateOrOpenCallback& callback) { 153 FileSystemOperationContext* context_ptr = context.release(); 154 const bool success = base::FileUtilProxy::RelayCreateOrOpen( 155 context_ptr->task_runner(), 156 Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()), 157 context_ptr, url, file_flags), 158 Bind(&FileSystemFileUtil::Close, Unretained(sync_file_util_.get()), 159 base::Owned(context_ptr)), 160 Bind(&RunCreateOrOpenCallback, callback)); 161 DCHECK(success); 162 } 163 164 void AsyncFileUtilAdapter::EnsureFileExists( 165 scoped_ptr<FileSystemOperationContext> context, 166 const FileSystemURL& url, 167 const EnsureFileExistsCallback& callback) { 168 EnsureFileExistsHelper* helper = new EnsureFileExistsHelper; 169 FileSystemOperationContext* context_ptr = context.release(); 170 const bool success = context_ptr->task_runner()->PostTaskAndReply( 171 FROM_HERE, 172 Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper), 173 sync_file_util_.get(), base::Owned(context_ptr), url), 174 Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback)); 175 DCHECK(success); 176 } 177 178 void AsyncFileUtilAdapter::CreateDirectory( 179 scoped_ptr<FileSystemOperationContext> context, 180 const FileSystemURL& url, 181 bool exclusive, 182 bool recursive, 183 const StatusCallback& callback) { 184 FileSystemOperationContext* context_ptr = context.release(); 185 const bool success = base::PostTaskAndReplyWithResult( 186 context_ptr->task_runner(), FROM_HERE, 187 Bind(&FileSystemFileUtil::CreateDirectory, 188 Unretained(sync_file_util_.get()), 189 base::Owned(context_ptr), url, exclusive, recursive), 190 callback); 191 DCHECK(success); 192 } 193 194 void AsyncFileUtilAdapter::GetFileInfo( 195 scoped_ptr<FileSystemOperationContext> context, 196 const FileSystemURL& url, 197 const GetFileInfoCallback& callback) { 198 FileSystemOperationContext* context_ptr = context.release(); 199 GetFileInfoHelper* helper = new GetFileInfoHelper; 200 const bool success = context_ptr->task_runner()->PostTaskAndReply( 201 FROM_HERE, 202 Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper), 203 sync_file_util_.get(), base::Owned(context_ptr), url), 204 Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback)); 205 DCHECK(success); 206 } 207 208 void AsyncFileUtilAdapter::ReadDirectory( 209 scoped_ptr<FileSystemOperationContext> context, 210 const FileSystemURL& url, 211 const ReadDirectoryCallback& callback) { 212 FileSystemOperationContext* context_ptr = context.release(); 213 ReadDirectoryHelper* helper = new ReadDirectoryHelper; 214 const bool success = context_ptr->task_runner()->PostTaskAndReply( 215 FROM_HERE, 216 Bind(&ReadDirectoryHelper::RunWork, Unretained(helper), 217 sync_file_util_.get(), base::Owned(context_ptr), url), 218 Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback)); 219 DCHECK(success); 220 } 221 222 void AsyncFileUtilAdapter::Touch( 223 scoped_ptr<FileSystemOperationContext> context, 224 const FileSystemURL& url, 225 const base::Time& last_access_time, 226 const base::Time& last_modified_time, 227 const StatusCallback& callback) { 228 FileSystemOperationContext* context_ptr = context.release(); 229 const bool success = base::PostTaskAndReplyWithResult( 230 context_ptr->task_runner(), FROM_HERE, 231 Bind(&FileSystemFileUtil::Touch, Unretained(sync_file_util_.get()), 232 base::Owned(context_ptr), url, 233 last_access_time, last_modified_time), 234 callback); 235 DCHECK(success); 236 } 237 238 void AsyncFileUtilAdapter::Truncate( 239 scoped_ptr<FileSystemOperationContext> context, 240 const FileSystemURL& url, 241 int64 length, 242 const StatusCallback& callback) { 243 FileSystemOperationContext* context_ptr = context.release(); 244 const bool success = base::PostTaskAndReplyWithResult( 245 context_ptr->task_runner(), FROM_HERE, 246 Bind(&FileSystemFileUtil::Truncate, Unretained(sync_file_util_.get()), 247 base::Owned(context_ptr), url, length), 248 callback); 249 DCHECK(success); 250 } 251 252 void AsyncFileUtilAdapter::CopyFileLocal( 253 scoped_ptr<FileSystemOperationContext> context, 254 const FileSystemURL& src_url, 255 const FileSystemURL& dest_url, 256 const StatusCallback& callback) { 257 FileSystemOperationContext* context_ptr = context.release(); 258 const bool success = base::PostTaskAndReplyWithResult( 259 context_ptr->task_runner(), FROM_HERE, 260 Bind(&FileSystemFileUtil::CopyOrMoveFile, 261 Unretained(sync_file_util_.get()), 262 base::Owned(context_ptr), src_url, dest_url, true /* copy */), 263 callback); 264 DCHECK(success); 265 } 266 267 void AsyncFileUtilAdapter::MoveFileLocal( 268 scoped_ptr<FileSystemOperationContext> context, 269 const FileSystemURL& src_url, 270 const FileSystemURL& dest_url, 271 const StatusCallback& callback) { 272 FileSystemOperationContext* context_ptr = context.release(); 273 const bool success = base::PostTaskAndReplyWithResult( 274 context_ptr->task_runner(), FROM_HERE, 275 Bind(&FileSystemFileUtil::CopyOrMoveFile, 276 Unretained(sync_file_util_.get()), 277 base::Owned(context_ptr), src_url, dest_url, false /* copy */), 278 callback); 279 DCHECK(success); 280 } 281 282 void AsyncFileUtilAdapter::CopyInForeignFile( 283 scoped_ptr<FileSystemOperationContext> context, 284 const base::FilePath& src_file_path, 285 const FileSystemURL& dest_url, 286 const StatusCallback& callback) { 287 FileSystemOperationContext* context_ptr = context.release(); 288 const bool success = base::PostTaskAndReplyWithResult( 289 context_ptr->task_runner(), FROM_HERE, 290 Bind(&FileSystemFileUtil::CopyInForeignFile, 291 Unretained(sync_file_util_.get()), 292 base::Owned(context_ptr), src_file_path, dest_url), 293 callback); 294 DCHECK(success); 295 } 296 297 void AsyncFileUtilAdapter::DeleteFile( 298 scoped_ptr<FileSystemOperationContext> context, 299 const FileSystemURL& url, 300 const StatusCallback& callback) { 301 FileSystemOperationContext* context_ptr = context.release(); 302 const bool success = base::PostTaskAndReplyWithResult( 303 context_ptr->task_runner(), FROM_HERE, 304 Bind(&FileSystemFileUtil::DeleteFile, 305 Unretained(sync_file_util_.get()), 306 base::Owned(context_ptr), url), 307 callback); 308 DCHECK(success); 309 } 310 311 void AsyncFileUtilAdapter::DeleteDirectory( 312 scoped_ptr<FileSystemOperationContext> context, 313 const FileSystemURL& url, 314 const StatusCallback& callback) { 315 FileSystemOperationContext* context_ptr = context.release(); 316 const bool success = base::PostTaskAndReplyWithResult( 317 context_ptr->task_runner(), FROM_HERE, 318 Bind(&FileSystemFileUtil::DeleteDirectory, 319 Unretained(sync_file_util_.get()), 320 base::Owned(context_ptr), url), 321 callback); 322 DCHECK(success); 323 } 324 325 void AsyncFileUtilAdapter::DeleteRecursively( 326 scoped_ptr<FileSystemOperationContext> context, 327 const FileSystemURL& url, 328 const StatusCallback& callback) { 329 callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); 330 } 331 332 void AsyncFileUtilAdapter::CreateSnapshotFile( 333 scoped_ptr<FileSystemOperationContext> context, 334 const FileSystemURL& url, 335 const CreateSnapshotFileCallback& callback) { 336 FileSystemOperationContext* context_ptr = context.release(); 337 GetFileInfoHelper* helper = new GetFileInfoHelper; 338 const bool success = context_ptr->task_runner()->PostTaskAndReply( 339 FROM_HERE, 340 Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper), 341 sync_file_util_.get(), base::Owned(context_ptr), url), 342 Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback)); 343 DCHECK(success); 344 } 345 346 } // namespace fileapi 347