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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/files/file_enumerator.h" 12 #include "base/files/file_util.h" 13 #include "base/strings/string_util.h" 14 #include "base/task_runner_util.h" 15 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 16 #include "content/public/browser/browser_thread.h" 17 #include "net/base/io_buffer.h" 18 #include "net/base/mime_sniffer.h" 19 #include "storage/browser/fileapi/file_system_context.h" 20 #include "storage/browser/fileapi/file_system_operation_context.h" 21 #include "storage/browser/fileapi/native_file_util.h" 22 #include "storage/common/blob/shareable_file_reference.h" 23 #include "url/gurl.h" 24 25 namespace { 26 27 // Returns true if the current thread is capable of doing IO. 28 bool IsOnTaskRunnerThread(storage::FileSystemOperationContext* context) { 29 return context->task_runner()->RunsTasksOnCurrentThread(); 30 } 31 32 base::File::Error IsMediaHeader(const char* buf, size_t length) { 33 if (length == 0) 34 return base::File::FILE_ERROR_SECURITY; 35 36 std::string mime_type; 37 if (!net::SniffMimeTypeFromLocalData(buf, length, &mime_type)) 38 return base::File::FILE_ERROR_SECURITY; 39 40 if (StartsWithASCII(mime_type, "image/", true) || 41 StartsWithASCII(mime_type, "audio/", true) || 42 StartsWithASCII(mime_type, "video/", true) || 43 mime_type == "application/x-shockwave-flash") { 44 return base::File::FILE_OK; 45 } 46 return base::File::FILE_ERROR_SECURITY; 47 } 48 49 void HoldFileRef( 50 const scoped_refptr<storage::ShareableFileReference>& file_ref) { 51 } 52 53 void DidOpenSnapshot( 54 const storage::AsyncFileUtil::CreateOrOpenCallback& callback, 55 const scoped_refptr<storage::ShareableFileReference>& file_ref, 56 base::File file) { 57 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 58 if (!file.IsValid()) { 59 callback.Run(file.Pass(), base::Closure()); 60 return; 61 } 62 callback.Run(file.Pass(), base::Bind(&HoldFileRef, file_ref)); 63 } 64 65 } // namespace 66 67 NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter* media_path_filter) 68 : media_path_filter_(media_path_filter), 69 weak_factory_(this) { 70 } 71 72 NativeMediaFileUtil::~NativeMediaFileUtil() { 73 } 74 75 // static 76 base::File::Error NativeMediaFileUtil::IsMediaFile( 77 const base::FilePath& path) { 78 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); 79 if (!file.IsValid()) 80 return file.error_details(); 81 82 char buffer[net::kMaxBytesToSniff]; 83 84 // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at. 85 int64 len = file.Read(0, buffer, net::kMaxBytesToSniff); 86 if (len < 0) 87 return base::File::FILE_ERROR_FAILED; 88 89 return IsMediaHeader(buffer, len); 90 } 91 92 // static 93 base::File::Error NativeMediaFileUtil::BufferIsMediaHeader( 94 net::IOBuffer* buf, size_t length) { 95 return IsMediaHeader(buf->data(), length); 96 } 97 98 // static 99 void NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen( 100 base::SequencedTaskRunner* media_task_runner, 101 int file_flags, 102 const storage::AsyncFileUtil::CreateOrOpenCallback& callback, 103 base::File::Error result, 104 const base::File::Info& file_info, 105 const base::FilePath& platform_path, 106 const scoped_refptr<storage::ShareableFileReference>& file_ref) { 107 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 108 if (result != base::File::FILE_OK) { 109 callback.Run(base::File(), base::Closure()); 110 return; 111 } 112 base::PostTaskAndReplyWithResult( 113 media_task_runner, 114 FROM_HERE, 115 base::Bind( 116 &storage::NativeFileUtil::CreateOrOpen, platform_path, file_flags), 117 base::Bind(&DidOpenSnapshot, callback, file_ref)); 118 } 119 120 void NativeMediaFileUtil::CreateOrOpen( 121 scoped_ptr<storage::FileSystemOperationContext> context, 122 const storage::FileSystemURL& url, 123 int file_flags, 124 const CreateOrOpenCallback& callback) { 125 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 126 // Returns an error if any unsupported flag is found. 127 if (file_flags & ~(base::File::FLAG_OPEN | 128 base::File::FLAG_READ | 129 base::File::FLAG_WRITE_ATTRIBUTES)) { 130 callback.Run(base::File(base::File::FILE_ERROR_SECURITY), base::Closure()); 131 return; 132 } 133 scoped_refptr<base::SequencedTaskRunner> task_runner = context->task_runner(); 134 CreateSnapshotFile( 135 context.Pass(), 136 url, 137 base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen, 138 task_runner, 139 file_flags, 140 callback)); 141 } 142 143 void NativeMediaFileUtil::EnsureFileExists( 144 scoped_ptr<storage::FileSystemOperationContext> context, 145 const storage::FileSystemURL& url, 146 const EnsureFileExistsCallback& callback) { 147 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 148 callback.Run(base::File::FILE_ERROR_SECURITY, false); 149 } 150 151 void NativeMediaFileUtil::CreateDirectory( 152 scoped_ptr<storage::FileSystemOperationContext> context, 153 const storage::FileSystemURL& url, 154 bool exclusive, 155 bool recursive, 156 const StatusCallback& callback) { 157 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 158 storage::FileSystemOperationContext* context_ptr = context.get(); 159 const bool success = context_ptr->task_runner()->PostTask( 160 FROM_HERE, 161 base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread, 162 weak_factory_.GetWeakPtr(), base::Passed(&context), 163 url, exclusive, recursive, callback)); 164 DCHECK(success); 165 } 166 167 void NativeMediaFileUtil::GetFileInfo( 168 scoped_ptr<storage::FileSystemOperationContext> context, 169 const storage::FileSystemURL& url, 170 const GetFileInfoCallback& callback) { 171 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 172 storage::FileSystemOperationContext* context_ptr = context.get(); 173 const bool success = context_ptr->task_runner()->PostTask( 174 FROM_HERE, 175 base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread, 176 weak_factory_.GetWeakPtr(), base::Passed(&context), 177 url, callback)); 178 DCHECK(success); 179 } 180 181 void NativeMediaFileUtil::ReadDirectory( 182 scoped_ptr<storage::FileSystemOperationContext> context, 183 const storage::FileSystemURL& url, 184 const ReadDirectoryCallback& callback) { 185 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 186 storage::FileSystemOperationContext* context_ptr = context.get(); 187 const bool success = context_ptr->task_runner()->PostTask( 188 FROM_HERE, 189 base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread, 190 weak_factory_.GetWeakPtr(), base::Passed(&context), 191 url, callback)); 192 DCHECK(success); 193 } 194 195 void NativeMediaFileUtil::Touch( 196 scoped_ptr<storage::FileSystemOperationContext> context, 197 const storage::FileSystemURL& url, 198 const base::Time& last_access_time, 199 const base::Time& last_modified_time, 200 const StatusCallback& callback) { 201 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 202 callback.Run(base::File::FILE_ERROR_SECURITY); 203 } 204 205 void NativeMediaFileUtil::Truncate( 206 scoped_ptr<storage::FileSystemOperationContext> context, 207 const storage::FileSystemURL& url, 208 int64 length, 209 const StatusCallback& callback) { 210 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 211 callback.Run(base::File::FILE_ERROR_SECURITY); 212 } 213 214 void NativeMediaFileUtil::CopyFileLocal( 215 scoped_ptr<storage::FileSystemOperationContext> context, 216 const storage::FileSystemURL& src_url, 217 const storage::FileSystemURL& dest_url, 218 CopyOrMoveOption option, 219 const CopyFileProgressCallback& progress_callback, 220 const StatusCallback& callback) { 221 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 222 storage::FileSystemOperationContext* context_ptr = context.get(); 223 const bool success = context_ptr->task_runner()->PostTask( 224 FROM_HERE, 225 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread, 226 weak_factory_.GetWeakPtr(), base::Passed(&context), 227 src_url, dest_url, option, true /* copy */, callback)); 228 DCHECK(success); 229 } 230 231 void NativeMediaFileUtil::MoveFileLocal( 232 scoped_ptr<storage::FileSystemOperationContext> context, 233 const storage::FileSystemURL& src_url, 234 const storage::FileSystemURL& dest_url, 235 CopyOrMoveOption option, 236 const StatusCallback& callback) { 237 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 238 storage::FileSystemOperationContext* context_ptr = context.get(); 239 const bool success = context_ptr->task_runner()->PostTask( 240 FROM_HERE, 241 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread, 242 weak_factory_.GetWeakPtr(), base::Passed(&context), 243 src_url, dest_url, option, false /* copy */, callback)); 244 DCHECK(success); 245 } 246 247 void NativeMediaFileUtil::CopyInForeignFile( 248 scoped_ptr<storage::FileSystemOperationContext> context, 249 const base::FilePath& src_file_path, 250 const storage::FileSystemURL& dest_url, 251 const StatusCallback& callback) { 252 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 253 storage::FileSystemOperationContext* context_ptr = context.get(); 254 const bool success = context_ptr->task_runner()->PostTask( 255 FROM_HERE, 256 base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread, 257 weak_factory_.GetWeakPtr(), base::Passed(&context), 258 src_file_path, dest_url, callback)); 259 DCHECK(success); 260 } 261 262 void NativeMediaFileUtil::DeleteFile( 263 scoped_ptr<storage::FileSystemOperationContext> context, 264 const storage::FileSystemURL& url, 265 const StatusCallback& callback) { 266 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 267 storage::FileSystemOperationContext* context_ptr = context.get(); 268 const bool success = context_ptr->task_runner()->PostTask( 269 FROM_HERE, 270 base::Bind(&NativeMediaFileUtil::DeleteFileOnTaskRunnerThread, 271 weak_factory_.GetWeakPtr(), base::Passed(&context), 272 url, callback)); 273 DCHECK(success); 274 } 275 276 // This is needed to support Copy and Move. 277 void NativeMediaFileUtil::DeleteDirectory( 278 scoped_ptr<storage::FileSystemOperationContext> context, 279 const storage::FileSystemURL& url, 280 const StatusCallback& callback) { 281 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 282 storage::FileSystemOperationContext* context_ptr = context.get(); 283 const bool success = context_ptr->task_runner()->PostTask( 284 FROM_HERE, 285 base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread, 286 weak_factory_.GetWeakPtr(), base::Passed(&context), 287 url, callback)); 288 DCHECK(success); 289 } 290 291 void NativeMediaFileUtil::DeleteRecursively( 292 scoped_ptr<storage::FileSystemOperationContext> context, 293 const storage::FileSystemURL& url, 294 const StatusCallback& callback) { 295 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 296 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); 297 } 298 299 void NativeMediaFileUtil::CreateSnapshotFile( 300 scoped_ptr<storage::FileSystemOperationContext> context, 301 const storage::FileSystemURL& url, 302 const CreateSnapshotFileCallback& callback) { 303 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 304 storage::FileSystemOperationContext* context_ptr = context.get(); 305 const bool success = context_ptr->task_runner()->PostTask( 306 FROM_HERE, 307 base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread, 308 weak_factory_.GetWeakPtr(), base::Passed(&context), 309 url, callback)); 310 DCHECK(success); 311 } 312 313 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread( 314 scoped_ptr<storage::FileSystemOperationContext> context, 315 const storage::FileSystemURL& url, 316 bool exclusive, 317 bool recursive, 318 const StatusCallback& callback) { 319 DCHECK(IsOnTaskRunnerThread(context.get())); 320 base::File::Error error = 321 CreateDirectorySync(context.get(), url, exclusive, recursive); 322 content::BrowserThread::PostTask( 323 content::BrowserThread::IO, 324 FROM_HERE, 325 base::Bind(callback, error)); 326 } 327 328 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread( 329 scoped_ptr<storage::FileSystemOperationContext> context, 330 const storage::FileSystemURL& url, 331 const GetFileInfoCallback& callback) { 332 DCHECK(IsOnTaskRunnerThread(context.get())); 333 base::File::Info file_info; 334 base::File::Error error = 335 GetFileInfoSync(context.get(), url, &file_info, NULL); 336 content::BrowserThread::PostTask( 337 content::BrowserThread::IO, 338 FROM_HERE, 339 base::Bind(callback, error, file_info)); 340 } 341 342 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread( 343 scoped_ptr<storage::FileSystemOperationContext> context, 344 const storage::FileSystemURL& url, 345 const ReadDirectoryCallback& callback) { 346 DCHECK(IsOnTaskRunnerThread(context.get())); 347 EntryList entry_list; 348 base::File::Error error = 349 ReadDirectorySync(context.get(), url, &entry_list); 350 content::BrowserThread::PostTask( 351 content::BrowserThread::IO, 352 FROM_HERE, 353 base::Bind(callback, error, entry_list, false /* has_more */)); 354 } 355 356 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread( 357 scoped_ptr<storage::FileSystemOperationContext> context, 358 const storage::FileSystemURL& src_url, 359 const storage::FileSystemURL& dest_url, 360 CopyOrMoveOption option, 361 bool copy, 362 const StatusCallback& callback) { 363 DCHECK(IsOnTaskRunnerThread(context.get())); 364 base::File::Error error = 365 CopyOrMoveFileSync(context.get(), src_url, dest_url, option, copy); 366 content::BrowserThread::PostTask( 367 content::BrowserThread::IO, 368 FROM_HERE, 369 base::Bind(callback, error)); 370 } 371 372 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread( 373 scoped_ptr<storage::FileSystemOperationContext> context, 374 const base::FilePath& src_file_path, 375 const storage::FileSystemURL& dest_url, 376 const StatusCallback& callback) { 377 DCHECK(IsOnTaskRunnerThread(context.get())); 378 base::File::Error error = 379 CopyInForeignFileSync(context.get(), src_file_path, dest_url); 380 content::BrowserThread::PostTask( 381 content::BrowserThread::IO, 382 FROM_HERE, 383 base::Bind(callback, error)); 384 } 385 386 void NativeMediaFileUtil::DeleteFileOnTaskRunnerThread( 387 scoped_ptr<storage::FileSystemOperationContext> context, 388 const storage::FileSystemURL& url, 389 const StatusCallback& callback) { 390 DCHECK(IsOnTaskRunnerThread(context.get())); 391 base::File::Error error = DeleteFileSync(context.get(), url); 392 content::BrowserThread::PostTask( 393 content::BrowserThread::IO, 394 FROM_HERE, 395 base::Bind(callback, error)); 396 } 397 398 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread( 399 scoped_ptr<storage::FileSystemOperationContext> context, 400 const storage::FileSystemURL& url, 401 const StatusCallback& callback) { 402 DCHECK(IsOnTaskRunnerThread(context.get())); 403 base::File::Error error = DeleteDirectorySync(context.get(), url); 404 content::BrowserThread::PostTask( 405 content::BrowserThread::IO, 406 FROM_HERE, 407 base::Bind(callback, error)); 408 } 409 410 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread( 411 scoped_ptr<storage::FileSystemOperationContext> context, 412 const storage::FileSystemURL& url, 413 const CreateSnapshotFileCallback& callback) { 414 DCHECK(IsOnTaskRunnerThread(context.get())); 415 base::File::Info file_info; 416 base::FilePath platform_path; 417 scoped_refptr<storage::ShareableFileReference> file_ref; 418 base::File::Error error = CreateSnapshotFileSync( 419 context.get(), url, &file_info, &platform_path, &file_ref); 420 content::BrowserThread::PostTask( 421 content::BrowserThread::IO, 422 FROM_HERE, 423 base::Bind(callback, error, file_info, platform_path, file_ref)); 424 } 425 426 base::File::Error NativeMediaFileUtil::CreateDirectorySync( 427 storage::FileSystemOperationContext* context, 428 const storage::FileSystemURL& url, 429 bool exclusive, 430 bool recursive) { 431 base::FilePath file_path; 432 base::File::Error error = GetLocalFilePath(context, url, &file_path); 433 if (error != base::File::FILE_OK) 434 return error; 435 return storage::NativeFileUtil::CreateDirectory( 436 file_path, exclusive, recursive); 437 } 438 439 base::File::Error NativeMediaFileUtil::CopyOrMoveFileSync( 440 storage::FileSystemOperationContext* context, 441 const storage::FileSystemURL& src_url, 442 const storage::FileSystemURL& dest_url, 443 CopyOrMoveOption option, 444 bool copy) { 445 DCHECK(IsOnTaskRunnerThread(context)); 446 base::FilePath src_file_path; 447 base::File::Error error = 448 GetFilteredLocalFilePathForExistingFileOrDirectory( 449 context, src_url, 450 base::File::FILE_ERROR_NOT_FOUND, 451 &src_file_path); 452 if (error != base::File::FILE_OK) 453 return error; 454 if (storage::NativeFileUtil::DirectoryExists(src_file_path)) 455 return base::File::FILE_ERROR_NOT_A_FILE; 456 457 base::FilePath dest_file_path; 458 error = GetLocalFilePath(context, dest_url, &dest_file_path); 459 if (error != base::File::FILE_OK) 460 return error; 461 base::File::Info file_info; 462 error = storage::NativeFileUtil::GetFileInfo(dest_file_path, &file_info); 463 if (error != base::File::FILE_OK && 464 error != base::File::FILE_ERROR_NOT_FOUND) { 465 return error; 466 } 467 if (error == base::File::FILE_OK && file_info.is_directory) 468 return base::File::FILE_ERROR_INVALID_OPERATION; 469 if (!media_path_filter_->Match(dest_file_path)) 470 return base::File::FILE_ERROR_SECURITY; 471 472 return storage::NativeFileUtil::CopyOrMoveFile( 473 src_file_path, 474 dest_file_path, 475 option, 476 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy)); 477 } 478 479 base::File::Error NativeMediaFileUtil::CopyInForeignFileSync( 480 storage::FileSystemOperationContext* context, 481 const base::FilePath& src_file_path, 482 const storage::FileSystemURL& dest_url) { 483 DCHECK(IsOnTaskRunnerThread(context)); 484 if (src_file_path.empty()) 485 return base::File::FILE_ERROR_INVALID_OPERATION; 486 487 base::FilePath dest_file_path; 488 base::File::Error error = 489 GetFilteredLocalFilePath(context, dest_url, &dest_file_path); 490 if (error != base::File::FILE_OK) 491 return error; 492 return storage::NativeFileUtil::CopyOrMoveFile( 493 src_file_path, 494 dest_file_path, 495 storage::FileSystemOperation::OPTION_NONE, 496 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, 497 true /* copy */)); 498 } 499 500 base::File::Error NativeMediaFileUtil::GetFileInfoSync( 501 storage::FileSystemOperationContext* context, 502 const storage::FileSystemURL& url, 503 base::File::Info* file_info, 504 base::FilePath* platform_path) { 505 DCHECK(context); 506 DCHECK(IsOnTaskRunnerThread(context)); 507 DCHECK(file_info); 508 509 base::FilePath file_path; 510 base::File::Error error = GetLocalFilePath(context, url, &file_path); 511 if (error != base::File::FILE_OK) 512 return error; 513 if (base::IsLink(file_path)) 514 return base::File::FILE_ERROR_NOT_FOUND; 515 error = storage::NativeFileUtil::GetFileInfo(file_path, file_info); 516 if (error != base::File::FILE_OK) 517 return error; 518 519 if (platform_path) 520 *platform_path = file_path; 521 if (file_info->is_directory || 522 media_path_filter_->Match(file_path)) { 523 return base::File::FILE_OK; 524 } 525 return base::File::FILE_ERROR_NOT_FOUND; 526 } 527 528 base::File::Error NativeMediaFileUtil::GetLocalFilePath( 529 storage::FileSystemOperationContext* context, 530 const storage::FileSystemURL& url, 531 base::FilePath* local_file_path) { 532 DCHECK(local_file_path); 533 DCHECK(url.is_valid()); 534 if (url.path().empty()) { 535 // Root direcory case, which should not be accessed. 536 return base::File::FILE_ERROR_ACCESS_DENIED; 537 } 538 *local_file_path = url.path(); 539 return base::File::FILE_OK; 540 } 541 542 base::File::Error NativeMediaFileUtil::ReadDirectorySync( 543 storage::FileSystemOperationContext* context, 544 const storage::FileSystemURL& url, 545 EntryList* file_list) { 546 DCHECK(IsOnTaskRunnerThread(context)); 547 DCHECK(file_list); 548 DCHECK(file_list->empty()); 549 base::File::Info file_info; 550 base::FilePath dir_path; 551 base::File::Error error = 552 GetFileInfoSync(context, url, &file_info, &dir_path); 553 554 if (error != base::File::FILE_OK) 555 return error; 556 557 if (!file_info.is_directory) 558 return base::File::FILE_ERROR_NOT_A_DIRECTORY; 559 560 base::FileEnumerator file_enum( 561 dir_path, 562 false /* recursive */, 563 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); 564 for (base::FilePath enum_path = file_enum.Next(); 565 !enum_path.empty(); 566 enum_path = file_enum.Next()) { 567 // Skip symlinks. 568 if (base::IsLink(enum_path)) 569 continue; 570 571 base::FileEnumerator::FileInfo info = file_enum.GetInfo(); 572 573 // NativeMediaFileUtil skip criteria. 574 if (MediaPathFilter::ShouldSkip(enum_path)) 575 continue; 576 if (!info.IsDirectory() && !media_path_filter_->Match(enum_path)) 577 continue; 578 579 storage::DirectoryEntry entry; 580 entry.is_directory = info.IsDirectory(); 581 entry.name = enum_path.BaseName().value(); 582 entry.size = info.GetSize(); 583 entry.last_modified_time = info.GetLastModifiedTime(); 584 585 file_list->push_back(entry); 586 } 587 588 return base::File::FILE_OK; 589 } 590 591 base::File::Error NativeMediaFileUtil::DeleteFileSync( 592 storage::FileSystemOperationContext* context, 593 const storage::FileSystemURL& url) { 594 DCHECK(IsOnTaskRunnerThread(context)); 595 base::File::Info file_info; 596 base::FilePath file_path; 597 base::File::Error error = 598 GetFileInfoSync(context, url, &file_info, &file_path); 599 if (error != base::File::FILE_OK) 600 return error; 601 if (file_info.is_directory) 602 return base::File::FILE_ERROR_NOT_A_FILE; 603 return storage::NativeFileUtil::DeleteFile(file_path); 604 } 605 606 base::File::Error NativeMediaFileUtil::DeleteDirectorySync( 607 storage::FileSystemOperationContext* context, 608 const storage::FileSystemURL& url) { 609 DCHECK(IsOnTaskRunnerThread(context)); 610 base::FilePath file_path; 611 base::File::Error error = GetLocalFilePath(context, url, &file_path); 612 if (error != base::File::FILE_OK) 613 return error; 614 return storage::NativeFileUtil::DeleteDirectory(file_path); 615 } 616 617 base::File::Error NativeMediaFileUtil::CreateSnapshotFileSync( 618 storage::FileSystemOperationContext* context, 619 const storage::FileSystemURL& url, 620 base::File::Info* file_info, 621 base::FilePath* platform_path, 622 scoped_refptr<storage::ShareableFileReference>* file_ref) { 623 DCHECK(IsOnTaskRunnerThread(context)); 624 base::File::Error error = 625 GetFileInfoSync(context, url, file_info, platform_path); 626 if (error == base::File::FILE_OK && file_info->is_directory) 627 error = base::File::FILE_ERROR_NOT_A_FILE; 628 if (error == base::File::FILE_OK) 629 error = NativeMediaFileUtil::IsMediaFile(*platform_path); 630 631 // We're just returning the local file information. 632 *file_ref = scoped_refptr<storage::ShareableFileReference>(); 633 634 return error; 635 } 636 637 base::File::Error NativeMediaFileUtil::GetFilteredLocalFilePath( 638 storage::FileSystemOperationContext* context, 639 const storage::FileSystemURL& file_system_url, 640 base::FilePath* local_file_path) { 641 DCHECK(IsOnTaskRunnerThread(context)); 642 base::FilePath file_path; 643 base::File::Error error = 644 GetLocalFilePath(context, file_system_url, &file_path); 645 if (error != base::File::FILE_OK) 646 return error; 647 if (!media_path_filter_->Match(file_path)) 648 return base::File::FILE_ERROR_SECURITY; 649 650 *local_file_path = file_path; 651 return base::File::FILE_OK; 652 } 653 654 base::File::Error 655 NativeMediaFileUtil::GetFilteredLocalFilePathForExistingFileOrDirectory( 656 storage::FileSystemOperationContext* context, 657 const storage::FileSystemURL& file_system_url, 658 base::File::Error failure_error, 659 base::FilePath* local_file_path) { 660 DCHECK(IsOnTaskRunnerThread(context)); 661 base::FilePath file_path; 662 base::File::Error error = 663 GetLocalFilePath(context, file_system_url, &file_path); 664 if (error != base::File::FILE_OK) 665 return error; 666 667 if (!base::PathExists(file_path)) 668 return failure_error; 669 base::File::Info file_info; 670 if (!base::GetFileInfo(file_path, &file_info)) 671 return base::File::FILE_ERROR_FAILED; 672 673 if (!file_info.is_directory && 674 !media_path_filter_->Match(file_path)) { 675 return failure_error; 676 } 677 678 *local_file_path = file_path; 679 return base::File::FILE_OK; 680 } 681