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 25namespace { 26 27// Returns true if the current thread is capable of doing IO. 28bool IsOnTaskRunnerThread(storage::FileSystemOperationContext* context) { 29 return context->task_runner()->RunsTasksOnCurrentThread(); 30} 31 32base::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 49void HoldFileRef( 50 const scoped_refptr<storage::ShareableFileReference>& file_ref) { 51} 52 53void 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 67NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter* media_path_filter) 68 : media_path_filter_(media_path_filter), 69 weak_factory_(this) { 70} 71 72NativeMediaFileUtil::~NativeMediaFileUtil() { 73} 74 75// static 76base::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 93base::File::Error NativeMediaFileUtil::BufferIsMediaHeader( 94 net::IOBuffer* buf, size_t length) { 95 return IsMediaHeader(buf->data(), length); 96} 97 98// static 99void 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 120void 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 143void 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 151void 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 167void 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 181void 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 195void 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 205void 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 214void 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 231void 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 247void 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 262void 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. 277void 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 291void 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 299void 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 313void 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 328void 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 342void 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 356void 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 372void 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 386void 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 398void 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 410void 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 426base::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 439base::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 479base::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 500base::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 528base::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 542base::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 591base::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 606base::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 617base::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 637base::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 654base::File::Error 655NativeMediaFileUtil::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