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