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/files/scoped_platform_file_closer.h" 14 #include "base/strings/string_util.h" 15 #include "base/task_runner_util.h" 16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 17 #include "content/public/browser/browser_thread.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 chrome { 26 27 namespace { 28 29 // Used to skip the hidden folders and files. Returns true if the file specified 30 // by |path| should be skipped. 31 bool ShouldSkip(const base::FilePath& path) { 32 const base::FilePath::StringType base_name = path.BaseName().value(); 33 if (base_name.empty()) 34 return false; 35 36 // Dot files (aka hidden files) 37 if (base_name[0] == '.') 38 return true; 39 40 // Mac OS X file. 41 if (base_name == FILE_PATH_LITERAL("__MACOSX")) 42 return true; 43 44 #if defined(OS_WIN) 45 DWORD file_attributes = ::GetFileAttributes(path.value().c_str()); 46 if ((file_attributes != INVALID_FILE_ATTRIBUTES) && 47 ((file_attributes & FILE_ATTRIBUTE_HIDDEN) != 0)) 48 return true; 49 #else 50 // Windows always creates a recycle bin folder in the attached device to store 51 // all the deleted contents. On non-windows operating systems, there is no way 52 // to get the hidden attribute of windows recycle bin folders that are present 53 // on the attached device. Therefore, compare the file path name to the 54 // recycle bin name and exclude those folders. For more details, please refer 55 // to http://support.microsoft.com/kb/171694. 56 const char win_98_recycle_bin_name[] = "RECYCLED"; 57 const char win_xp_recycle_bin_name[] = "RECYCLER"; 58 const char win_vista_recycle_bin_name[] = "$Recycle.bin"; 59 if ((base::strncasecmp(base_name.c_str(), 60 win_98_recycle_bin_name, 61 strlen(win_98_recycle_bin_name)) == 0) || 62 (base::strncasecmp(base_name.c_str(), 63 win_xp_recycle_bin_name, 64 strlen(win_xp_recycle_bin_name)) == 0) || 65 (base::strncasecmp(base_name.c_str(), 66 win_vista_recycle_bin_name, 67 strlen(win_vista_recycle_bin_name)) == 0)) 68 return true; 69 #endif 70 return false; 71 } 72 73 // Returns true if the current thread is capable of doing IO. 74 bool IsOnTaskRunnerThread(fileapi::FileSystemOperationContext* context) { 75 return context->task_runner()->RunsTasksOnCurrentThread(); 76 } 77 78 } // namespace 79 80 NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter* media_path_filter) 81 : weak_factory_(this), 82 media_path_filter_(media_path_filter) { 83 } 84 85 NativeMediaFileUtil::~NativeMediaFileUtil() { 86 } 87 88 // static 89 base::PlatformFileError NativeMediaFileUtil::IsMediaFile( 90 const base::FilePath& path) { 91 base::PlatformFile file_handle; 92 const int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; 93 base::PlatformFileError error = 94 fileapi::NativeFileUtil::CreateOrOpen(path, flags, &file_handle, NULL); 95 if (error != base::PLATFORM_FILE_OK) 96 return error; 97 98 base::ScopedPlatformFileCloser scoped_platform_file(&file_handle); 99 char buffer[net::kMaxBytesToSniff]; 100 101 // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at. 102 int64 len = 103 base::ReadPlatformFile(file_handle, 0, buffer, net::kMaxBytesToSniff); 104 if (len < 0) 105 return base::PLATFORM_FILE_ERROR_FAILED; 106 if (len == 0) 107 return base::PLATFORM_FILE_ERROR_SECURITY; 108 109 std::string mime_type; 110 if (!net::SniffMimeTypeFromLocalData(buffer, len, &mime_type)) 111 return base::PLATFORM_FILE_ERROR_SECURITY; 112 113 if (StartsWithASCII(mime_type, "image/", true) || 114 StartsWithASCII(mime_type, "audio/", true) || 115 StartsWithASCII(mime_type, "video/", true) || 116 mime_type == "application/x-shockwave-flash") { 117 return base::PLATFORM_FILE_OK; 118 } 119 return base::PLATFORM_FILE_ERROR_SECURITY; 120 } 121 122 void NativeMediaFileUtil::CreateOrOpen( 123 scoped_ptr<fileapi::FileSystemOperationContext> context, 124 const fileapi::FileSystemURL& url, 125 int file_flags, 126 const CreateOrOpenCallback& callback) { 127 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 128 // Only called by NaCl, which should not have access to media file systems. 129 base::PlatformFile invalid_file(base::kInvalidPlatformFileValue); 130 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, 131 base::PassPlatformFile(&invalid_file), 132 base::Closure()); 133 } 134 135 void NativeMediaFileUtil::EnsureFileExists( 136 scoped_ptr<fileapi::FileSystemOperationContext> context, 137 const fileapi::FileSystemURL& url, 138 const EnsureFileExistsCallback& callback) { 139 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 140 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, false); 141 } 142 143 void NativeMediaFileUtil::CreateDirectory( 144 scoped_ptr<fileapi::FileSystemOperationContext> context, 145 const fileapi::FileSystemURL& url, 146 bool exclusive, 147 bool recursive, 148 const StatusCallback& callback) { 149 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 150 fileapi::FileSystemOperationContext* context_ptr = context.get(); 151 const bool success = context_ptr->task_runner()->PostTask( 152 FROM_HERE, 153 base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread, 154 weak_factory_.GetWeakPtr(), base::Passed(&context), 155 url, exclusive, recursive, callback)); 156 DCHECK(success); 157 } 158 159 void NativeMediaFileUtil::GetFileInfo( 160 scoped_ptr<fileapi::FileSystemOperationContext> context, 161 const fileapi::FileSystemURL& url, 162 const GetFileInfoCallback& callback) { 163 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 164 fileapi::FileSystemOperationContext* context_ptr = context.get(); 165 const bool success = context_ptr->task_runner()->PostTask( 166 FROM_HERE, 167 base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread, 168 weak_factory_.GetWeakPtr(), base::Passed(&context), 169 url, callback)); 170 DCHECK(success); 171 } 172 173 void NativeMediaFileUtil::ReadDirectory( 174 scoped_ptr<fileapi::FileSystemOperationContext> context, 175 const fileapi::FileSystemURL& url, 176 const ReadDirectoryCallback& callback) { 177 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 178 fileapi::FileSystemOperationContext* context_ptr = context.get(); 179 const bool success = context_ptr->task_runner()->PostTask( 180 FROM_HERE, 181 base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread, 182 weak_factory_.GetWeakPtr(), base::Passed(&context), 183 url, callback)); 184 DCHECK(success); 185 } 186 187 void NativeMediaFileUtil::Touch( 188 scoped_ptr<fileapi::FileSystemOperationContext> context, 189 const fileapi::FileSystemURL& url, 190 const base::Time& last_access_time, 191 const base::Time& last_modified_time, 192 const StatusCallback& callback) { 193 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 194 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); 195 } 196 197 void NativeMediaFileUtil::Truncate( 198 scoped_ptr<fileapi::FileSystemOperationContext> context, 199 const fileapi::FileSystemURL& url, 200 int64 length, 201 const StatusCallback& callback) { 202 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 203 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); 204 } 205 206 void NativeMediaFileUtil::CopyFileLocal( 207 scoped_ptr<fileapi::FileSystemOperationContext> context, 208 const fileapi::FileSystemURL& src_url, 209 const fileapi::FileSystemURL& dest_url, 210 const StatusCallback& callback) { 211 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 212 fileapi::FileSystemOperationContext* context_ptr = context.get(); 213 const bool success = context_ptr->task_runner()->PostTask( 214 FROM_HERE, 215 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread, 216 weak_factory_.GetWeakPtr(), base::Passed(&context), 217 src_url, dest_url, true /* copy */, callback)); 218 DCHECK(success); 219 } 220 221 void NativeMediaFileUtil::MoveFileLocal( 222 scoped_ptr<fileapi::FileSystemOperationContext> context, 223 const fileapi::FileSystemURL& src_url, 224 const fileapi::FileSystemURL& dest_url, 225 const StatusCallback& callback) { 226 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 227 fileapi::FileSystemOperationContext* context_ptr = context.get(); 228 const bool success = context_ptr->task_runner()->PostTask( 229 FROM_HERE, 230 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread, 231 weak_factory_.GetWeakPtr(), base::Passed(&context), 232 src_url, dest_url, false /* copy */, callback)); 233 DCHECK(success); 234 } 235 236 void NativeMediaFileUtil::CopyInForeignFile( 237 scoped_ptr<fileapi::FileSystemOperationContext> context, 238 const base::FilePath& src_file_path, 239 const fileapi::FileSystemURL& dest_url, 240 const StatusCallback& callback) { 241 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 242 fileapi::FileSystemOperationContext* context_ptr = context.get(); 243 const bool success = context_ptr->task_runner()->PostTask( 244 FROM_HERE, 245 base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread, 246 weak_factory_.GetWeakPtr(), base::Passed(&context), 247 src_file_path, dest_url, callback)); 248 DCHECK(success); 249 } 250 251 void NativeMediaFileUtil::DeleteFile( 252 scoped_ptr<fileapi::FileSystemOperationContext> context, 253 const fileapi::FileSystemURL& url, 254 const StatusCallback& callback) { 255 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 256 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); 257 } 258 259 // This is needed to support Copy and Move. 260 void NativeMediaFileUtil::DeleteDirectory( 261 scoped_ptr<fileapi::FileSystemOperationContext> context, 262 const fileapi::FileSystemURL& url, 263 const StatusCallback& callback) { 264 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 265 fileapi::FileSystemOperationContext* context_ptr = context.get(); 266 const bool success = context_ptr->task_runner()->PostTask( 267 FROM_HERE, 268 base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread, 269 weak_factory_.GetWeakPtr(), base::Passed(&context), 270 url, callback)); 271 DCHECK(success); 272 } 273 274 void NativeMediaFileUtil::DeleteRecursively( 275 scoped_ptr<fileapi::FileSystemOperationContext> context, 276 const fileapi::FileSystemURL& url, 277 const StatusCallback& callback) { 278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 279 callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); 280 } 281 282 void NativeMediaFileUtil::CreateSnapshotFile( 283 scoped_ptr<fileapi::FileSystemOperationContext> context, 284 const fileapi::FileSystemURL& url, 285 const CreateSnapshotFileCallback& callback) { 286 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 287 fileapi::FileSystemOperationContext* context_ptr = context.get(); 288 const bool success = context_ptr->task_runner()->PostTask( 289 FROM_HERE, 290 base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread, 291 weak_factory_.GetWeakPtr(), base::Passed(&context), 292 url, callback)); 293 DCHECK(success); 294 } 295 296 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread( 297 scoped_ptr<fileapi::FileSystemOperationContext> context, 298 const fileapi::FileSystemURL& url, 299 bool exclusive, 300 bool recursive, 301 const StatusCallback& callback) { 302 DCHECK(IsOnTaskRunnerThread(context.get())); 303 base::PlatformFileError error = 304 CreateDirectorySync(context.get(), url, exclusive, recursive); 305 content::BrowserThread::PostTask( 306 content::BrowserThread::IO, 307 FROM_HERE, 308 base::Bind(callback, error)); 309 } 310 311 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread( 312 scoped_ptr<fileapi::FileSystemOperationContext> context, 313 const fileapi::FileSystemURL& url, 314 const GetFileInfoCallback& callback) { 315 DCHECK(IsOnTaskRunnerThread(context.get())); 316 base::PlatformFileInfo file_info; 317 base::PlatformFileError error = 318 GetFileInfoSync(context.get(), url, &file_info, NULL); 319 content::BrowserThread::PostTask( 320 content::BrowserThread::IO, 321 FROM_HERE, 322 base::Bind(callback, error, file_info)); 323 } 324 325 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread( 326 scoped_ptr<fileapi::FileSystemOperationContext> context, 327 const fileapi::FileSystemURL& url, 328 const ReadDirectoryCallback& callback) { 329 DCHECK(IsOnTaskRunnerThread(context.get())); 330 EntryList entry_list; 331 base::PlatformFileError error = 332 ReadDirectorySync(context.get(), url, &entry_list); 333 content::BrowserThread::PostTask( 334 content::BrowserThread::IO, 335 FROM_HERE, 336 base::Bind(callback, error, entry_list, false /* has_more */)); 337 } 338 339 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread( 340 scoped_ptr<fileapi::FileSystemOperationContext> context, 341 const fileapi::FileSystemURL& src_url, 342 const fileapi::FileSystemURL& dest_url, 343 bool copy, 344 const StatusCallback& callback) { 345 DCHECK(IsOnTaskRunnerThread(context.get())); 346 base::PlatformFileError error = 347 CopyOrMoveFileSync(context.get(), src_url, dest_url, copy); 348 content::BrowserThread::PostTask( 349 content::BrowserThread::IO, 350 FROM_HERE, 351 base::Bind(callback, error)); 352 } 353 354 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread( 355 scoped_ptr<fileapi::FileSystemOperationContext> context, 356 const base::FilePath& src_file_path, 357 const fileapi::FileSystemURL& dest_url, 358 const StatusCallback& callback) { 359 DCHECK(IsOnTaskRunnerThread(context.get())); 360 base::PlatformFileError error = 361 CopyInForeignFileSync(context.get(), src_file_path, dest_url); 362 content::BrowserThread::PostTask( 363 content::BrowserThread::IO, 364 FROM_HERE, 365 base::Bind(callback, error)); 366 } 367 368 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread( 369 scoped_ptr<fileapi::FileSystemOperationContext> context, 370 const fileapi::FileSystemURL& url, 371 const StatusCallback& callback) { 372 DCHECK(IsOnTaskRunnerThread(context.get())); 373 base::PlatformFileError error = DeleteDirectorySync(context.get(), url); 374 content::BrowserThread::PostTask( 375 content::BrowserThread::IO, 376 FROM_HERE, 377 base::Bind(callback, error)); 378 } 379 380 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread( 381 scoped_ptr<fileapi::FileSystemOperationContext> context, 382 const fileapi::FileSystemURL& url, 383 const CreateSnapshotFileCallback& callback) { 384 DCHECK(IsOnTaskRunnerThread(context.get())); 385 base::PlatformFileInfo file_info; 386 base::FilePath platform_path; 387 scoped_refptr<webkit_blob::ShareableFileReference> file_ref; 388 base::PlatformFileError error = 389 CreateSnapshotFileSync(context.get(), url, &file_info, &platform_path, 390 &file_ref); 391 content::BrowserThread::PostTask( 392 content::BrowserThread::IO, 393 FROM_HERE, 394 base::Bind(callback, error, file_info, platform_path, file_ref)); 395 } 396 397 base::PlatformFileError NativeMediaFileUtil::CreateDirectorySync( 398 fileapi::FileSystemOperationContext* context, 399 const fileapi::FileSystemURL& url, 400 bool exclusive, 401 bool recursive) { 402 base::FilePath file_path; 403 base::PlatformFileError error = GetLocalFilePath(context, url, &file_path); 404 if (error != base::PLATFORM_FILE_OK) 405 return error; 406 return fileapi::NativeFileUtil::CreateDirectory(file_path, exclusive, 407 recursive); 408 } 409 410 base::PlatformFileError NativeMediaFileUtil::CopyOrMoveFileSync( 411 fileapi::FileSystemOperationContext* context, 412 const fileapi::FileSystemURL& src_url, 413 const fileapi::FileSystemURL& dest_url, 414 bool copy) { 415 DCHECK(IsOnTaskRunnerThread(context)); 416 base::FilePath src_file_path; 417 base::PlatformFileError error = 418 GetFilteredLocalFilePathForExistingFileOrDirectory( 419 context, src_url, 420 base::PLATFORM_FILE_ERROR_NOT_FOUND, 421 &src_file_path); 422 if (error != base::PLATFORM_FILE_OK) 423 return error; 424 if (fileapi::NativeFileUtil::DirectoryExists(src_file_path)) 425 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; 426 427 base::FilePath dest_file_path; 428 error = GetLocalFilePath(context, dest_url, &dest_file_path); 429 if (error != base::PLATFORM_FILE_OK) 430 return error; 431 base::PlatformFileInfo file_info; 432 error = fileapi::NativeFileUtil::GetFileInfo(dest_file_path, &file_info); 433 if (error != base::PLATFORM_FILE_OK && 434 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) 435 return error; 436 if (error == base::PLATFORM_FILE_OK && file_info.is_directory) 437 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; 438 if (!media_path_filter_->Match(dest_file_path)) 439 return base::PLATFORM_FILE_ERROR_SECURITY; 440 441 return fileapi::NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path, 442 copy); 443 } 444 445 base::PlatformFileError NativeMediaFileUtil::CopyInForeignFileSync( 446 fileapi::FileSystemOperationContext* context, 447 const base::FilePath& src_file_path, 448 const fileapi::FileSystemURL& dest_url) { 449 DCHECK(IsOnTaskRunnerThread(context)); 450 if (src_file_path.empty()) 451 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; 452 453 base::FilePath dest_file_path; 454 base::PlatformFileError error = 455 GetFilteredLocalFilePath(context, dest_url, &dest_file_path); 456 if (error != base::PLATFORM_FILE_OK) 457 return error; 458 return fileapi::NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path, 459 true); 460 } 461 462 base::PlatformFileError NativeMediaFileUtil::GetFileInfoSync( 463 fileapi::FileSystemOperationContext* context, 464 const fileapi::FileSystemURL& url, 465 base::PlatformFileInfo* file_info, 466 base::FilePath* platform_path) { 467 DCHECK(context); 468 DCHECK(IsOnTaskRunnerThread(context)); 469 DCHECK(file_info); 470 471 base::FilePath file_path; 472 base::PlatformFileError error = GetLocalFilePath(context, url, &file_path); 473 if (error != base::PLATFORM_FILE_OK) 474 return error; 475 if (file_util::IsLink(file_path)) 476 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 477 error = fileapi::NativeFileUtil::GetFileInfo(file_path, file_info); 478 if (error != base::PLATFORM_FILE_OK) 479 return error; 480 481 if (platform_path) 482 *platform_path = file_path; 483 if (file_info->is_directory || 484 media_path_filter_->Match(file_path)) { 485 return base::PLATFORM_FILE_OK; 486 } 487 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 488 } 489 490 base::PlatformFileError NativeMediaFileUtil::GetLocalFilePath( 491 fileapi::FileSystemOperationContext* context, 492 const fileapi::FileSystemURL& url, 493 base::FilePath* local_file_path) { 494 DCHECK(local_file_path); 495 DCHECK(url.is_valid()); 496 if (url.path().empty()) { 497 // Root direcory case, which should not be accessed. 498 return base::PLATFORM_FILE_ERROR_ACCESS_DENIED; 499 } 500 *local_file_path = url.path(); 501 return base::PLATFORM_FILE_OK; 502 } 503 504 base::PlatformFileError NativeMediaFileUtil::ReadDirectorySync( 505 fileapi::FileSystemOperationContext* context, 506 const fileapi::FileSystemURL& url, 507 EntryList* file_list) { 508 DCHECK(IsOnTaskRunnerThread(context)); 509 DCHECK(file_list); 510 DCHECK(file_list->empty()); 511 base::PlatformFileInfo file_info; 512 base::FilePath dir_path; 513 base::PlatformFileError error = 514 GetFileInfoSync(context, url, &file_info, &dir_path); 515 516 if (error != base::PLATFORM_FILE_OK) 517 return error; 518 519 if (!file_info.is_directory) 520 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; 521 522 base::FileEnumerator file_enum( 523 dir_path, 524 false /* recursive */, 525 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); 526 for (base::FilePath enum_path = file_enum.Next(); 527 !enum_path.empty(); 528 enum_path = file_enum.Next()) { 529 // Skip symlinks. 530 if (file_util::IsLink(enum_path)) 531 continue; 532 533 base::FileEnumerator::FileInfo info = file_enum.GetInfo(); 534 535 // NativeMediaFileUtil skip criteria. 536 if (ShouldSkip(enum_path)) 537 continue; 538 if (!info.IsDirectory() && !media_path_filter_->Match(enum_path)) 539 continue; 540 541 fileapi::DirectoryEntry entry; 542 entry.is_directory = info.IsDirectory(); 543 entry.name = enum_path.BaseName().value(); 544 entry.size = info.GetSize(); 545 entry.last_modified_time = info.GetLastModifiedTime(); 546 547 file_list->push_back(entry); 548 } 549 550 return base::PLATFORM_FILE_OK; 551 } 552 553 base::PlatformFileError NativeMediaFileUtil::DeleteDirectorySync( 554 fileapi::FileSystemOperationContext* context, 555 const fileapi::FileSystemURL& url) { 556 DCHECK(IsOnTaskRunnerThread(context)); 557 base::FilePath file_path; 558 base::PlatformFileError error = GetLocalFilePath(context, url, &file_path); 559 if (error != base::PLATFORM_FILE_OK) 560 return error; 561 return fileapi::NativeFileUtil::DeleteDirectory(file_path); 562 } 563 564 base::PlatformFileError NativeMediaFileUtil::CreateSnapshotFileSync( 565 fileapi::FileSystemOperationContext* context, 566 const fileapi::FileSystemURL& url, 567 base::PlatformFileInfo* file_info, 568 base::FilePath* platform_path, 569 scoped_refptr<webkit_blob::ShareableFileReference>* file_ref) { 570 DCHECK(IsOnTaskRunnerThread(context)); 571 base::PlatformFileError error = 572 GetFileInfoSync(context, url, file_info, platform_path); 573 if (error == base::PLATFORM_FILE_OK && file_info->is_directory) 574 error = base::PLATFORM_FILE_ERROR_NOT_A_FILE; 575 if (error == base::PLATFORM_FILE_OK) 576 error = NativeMediaFileUtil::IsMediaFile(*platform_path); 577 578 // We're just returning the local file information. 579 *file_ref = scoped_refptr<webkit_blob::ShareableFileReference>(); 580 581 return error; 582 } 583 584 base::PlatformFileError NativeMediaFileUtil::GetFilteredLocalFilePath( 585 fileapi::FileSystemOperationContext* context, 586 const fileapi::FileSystemURL& file_system_url, 587 base::FilePath* local_file_path) { 588 DCHECK(IsOnTaskRunnerThread(context)); 589 base::FilePath file_path; 590 base::PlatformFileError error = 591 GetLocalFilePath(context, file_system_url, &file_path); 592 if (error != base::PLATFORM_FILE_OK) 593 return error; 594 if (!media_path_filter_->Match(file_path)) 595 return base::PLATFORM_FILE_ERROR_SECURITY; 596 597 *local_file_path = file_path; 598 return base::PLATFORM_FILE_OK; 599 } 600 601 base::PlatformFileError 602 NativeMediaFileUtil::GetFilteredLocalFilePathForExistingFileOrDirectory( 603 fileapi::FileSystemOperationContext* context, 604 const fileapi::FileSystemURL& file_system_url, 605 base::PlatformFileError failure_error, 606 base::FilePath* local_file_path) { 607 DCHECK(IsOnTaskRunnerThread(context)); 608 base::FilePath file_path; 609 base::PlatformFileError error = 610 GetLocalFilePath(context, file_system_url, &file_path); 611 if (error != base::PLATFORM_FILE_OK) 612 return error; 613 614 if (!base::PathExists(file_path)) 615 return failure_error; 616 base::PlatformFileInfo file_info; 617 if (!file_util::GetFileInfo(file_path, &file_info)) 618 return base::PLATFORM_FILE_ERROR_FAILED; 619 620 if (!file_info.is_directory && 621 !media_path_filter_->Match(file_path)) { 622 return failure_error; 623 } 624 625 *local_file_path = file_path; 626 return base::PLATFORM_FILE_OK; 627 } 628 629 } // namespace chrome 630