Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: chrome/browser/extensions/api/file_system/file_system_api.cc

Issue 23146016: Add support for directory access to the file system API. (Closed) Base URL: http://git.chromium.org/chromium/src.git@simpler-write-permissions
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/file_system/file_system_api.h" 5 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
6 6
7 #include "apps/saved_files_service.h" 7 #include "apps/saved_files_service.h"
8 #include "apps/shell_window.h" 8 #include "apps/shell_window.h"
9 #include "apps/shell_window_registry.h" 9 #include "apps/shell_window_registry.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 using fileapi::IsolatedContext; 53 using fileapi::IsolatedContext;
54 54
55 const char kInvalidParameters[] = "Invalid parameters"; 55 const char kInvalidParameters[] = "Invalid parameters";
56 const char kSecurityError[] = "Security error"; 56 const char kSecurityError[] = "Security error";
57 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " 57 const char kInvalidCallingPage[] = "Invalid calling page. This function can't "
58 "be called from a background page."; 58 "be called from a background page.";
59 const char kUserCancelled[] = "User cancelled"; 59 const char kUserCancelled[] = "User cancelled";
60 const char kWritableFileErrorFormat[] = "Error opening %s"; 60 const char kWritableFileErrorFormat[] = "Error opening %s";
61 const char kRequiresFileSystemWriteError[] = 61 const char kRequiresFileSystemWriteError[] =
62 "Operation requires fileSystem.write permission"; 62 "Operation requires fileSystem.write permission";
63 const char kRequiresFileSystemDirectoryError[] =
64 "Operation requires fileSystem.directory permission";
63 const char kMultipleUnsupportedError[] = 65 const char kMultipleUnsupportedError[] =
64 "acceptsMultiple: true is not supported for 'saveFile'"; 66 "acceptsMultiple: true is not supported for 'saveFile'";
65 const char kUnknownIdError[] = "Unknown id"; 67 const char kUnknownIdError[] = "Unknown id";
66 68
67 namespace file_system = extensions::api::file_system; 69 namespace file_system = extensions::api::file_system;
68 namespace ChooseEntry = file_system::ChooseEntry; 70 namespace ChooseEntry = file_system::ChooseEntry;
69 71
70 namespace { 72 namespace {
71 73
72 #if defined(OS_MACOSX) 74 #if defined(OS_MACOSX)
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 render_view_host_, &file_path, &error_)) 299 render_view_host_, &file_path, &error_))
298 return false; 300 return false;
299 301
300 file_path = PrettifyPath(file_path); 302 file_path = PrettifyPath(file_path);
301 SetResult(new base::StringValue(file_path.value())); 303 SetResult(new base::StringValue(file_path.value()));
302 return true; 304 return true;
303 } 305 }
304 306
305 FileSystemEntryFunction::FileSystemEntryFunction() 307 FileSystemEntryFunction::FileSystemEntryFunction()
306 : multiple_(false), 308 : multiple_(false),
309 is_directory_(false),
307 response_(NULL) {} 310 response_(NULL) {}
308 311
309 void FileSystemEntryFunction::CheckWritableFiles( 312 void FileSystemEntryFunction::CheckWritableFiles(
310 const std::vector<base::FilePath>& paths) { 313 const std::vector<base::FilePath>& paths) {
311 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 314 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
312 app_file_handler_util::CheckWritableFiles( 315 app_file_handler_util::CheckWritableFiles(
313 paths, 316 paths,
314 profile_, 317 profile_,
318 is_directory_,
315 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse, 319 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse,
316 this, 320 this,
317 paths), 321 paths),
318 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this)); 322 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this));
319 } 323 }
320 324
321 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse( 325 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse(
322 const std::vector<base::FilePath>& paths) { 326 const std::vector<base::FilePath>& paths) {
323 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 327 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
324 328
(...skipping 16 matching lines...) Expand all
341 345
342 void FileSystemEntryFunction::AddEntryToResponse( 346 void FileSystemEntryFunction::AddEntryToResponse(
343 const base::FilePath& path, 347 const base::FilePath& path,
344 const std::string& id_override) { 348 const std::string& id_override) {
345 DCHECK(response_); 349 DCHECK(response_);
346 extensions::app_file_handler_util::GrantedFileEntry file_entry = 350 extensions::app_file_handler_util::GrantedFileEntry file_entry =
347 extensions::app_file_handler_util::CreateFileEntry( 351 extensions::app_file_handler_util::CreateFileEntry(
348 profile(), 352 profile(),
349 GetExtension(), 353 GetExtension(),
350 render_view_host_->GetProcess()->GetID(), 354 render_view_host_->GetProcess()->GetID(),
351 path); 355 path,
356 is_directory_);
352 base::ListValue* entries; 357 base::ListValue* entries;
353 bool success = response_->GetList("entries", &entries); 358 bool success = response_->GetList("entries", &entries);
354 DCHECK(success); 359 DCHECK(success);
355 360
356 base::DictionaryValue* entry = new base::DictionaryValue(); 361 base::DictionaryValue* entry = new base::DictionaryValue();
357 entry->SetString("fileSystemId", file_entry.filesystem_id); 362 entry->SetString("fileSystemId", file_entry.filesystem_id);
358 entry->SetString("baseName", file_entry.registered_name); 363 entry->SetString("baseName", file_entry.registered_name);
359 if (id_override.empty()) 364 if (id_override.empty())
360 entry->SetString("id", file_entry.id); 365 entry->SetString("id", file_entry.id);
361 else 366 else
362 entry->SetString("id", id_override); 367 entry->SetString("id", id_override);
368 entry->SetBoolean("isDirectory", is_directory_);
363 entries->Append(entry); 369 entries->Append(entry);
364 } 370 }
365 371
366 void FileSystemEntryFunction::HandleWritableFileError( 372 void FileSystemEntryFunction::HandleWritableFileError(
367 const base::FilePath& error_path) { 373 const base::FilePath& error_path) {
368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 374 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
369 error_ = base::StringPrintf(kWritableFileErrorFormat, 375 error_ = base::StringPrintf(kWritableFileErrorFormat,
370 error_path.BaseName().AsUTF8Unsafe().c_str()); 376 error_path.BaseName().AsUTF8Unsafe().c_str());
371 SendResponse(false); 377 SendResponse(false);
372 } 378 }
373 379
374 bool FileSystemGetWritableEntryFunction::RunImpl() { 380 bool FileSystemGetWritableEntryFunction::RunImpl() {
375 std::string filesystem_name; 381 std::string filesystem_name;
376 std::string filesystem_path; 382 std::string filesystem_path;
377 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 383 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
378 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 384 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
379 385
380 if (!app_file_handler_util::HasFileSystemWritePermission(extension_)) { 386 if (!app_file_handler_util::HasFileSystemWritePermission(extension_)) {
381 error_ = kRequiresFileSystemWriteError; 387 error_ = kRequiresFileSystemWriteError;
382 return false; 388 return false;
383 } 389 }
384 390
385 base::FilePath path;
386 if (!ValidateFileEntryAndGetPath(filesystem_name, filesystem_path, 391 if (!ValidateFileEntryAndGetPath(filesystem_name, filesystem_path,
387 render_view_host_, &path, &error_)) 392 render_view_host_, &path_, &error_))
388 return false; 393 return false;
389 394
390 std::vector<base::FilePath> paths; 395 content::BrowserThread::PostTaskAndReply(
391 paths.push_back(path); 396 content::BrowserThread::FILE,
392 CheckWritableFiles(paths); 397 FROM_HERE,
398 base::Bind(
399 &FileSystemGetWritableEntryFunction::SetIsDirectoryOnFileThread,
400 this),
401 base::Bind(
402 &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse,
403 this));
393 return true; 404 return true;
394 } 405 }
395 406
407 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() {
408 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
409 if (is_directory_ &&
410 !extension_->HasAPIPermission(APIPermission::kFileSystemDirectory)) {
411 error_ = kRequiresFileSystemDirectoryError;
412 SendResponse(false);
413 }
414 std::vector<base::FilePath> paths;
415 paths.push_back(path_);
416 CheckWritableFiles(paths);
417 }
418
419 void FileSystemGetWritableEntryFunction::SetIsDirectoryOnFileThread() {
420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
421 if (base::DirectoryExists(path_)) {
422 is_directory_ = true;
423 }
424 }
425
396 bool FileSystemIsWritableEntryFunction::RunImpl() { 426 bool FileSystemIsWritableEntryFunction::RunImpl() {
397 std::string filesystem_name; 427 std::string filesystem_name;
398 std::string filesystem_path; 428 std::string filesystem_path;
399 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 429 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
400 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 430 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
401 431
402 std::string filesystem_id; 432 std::string filesystem_id;
403 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) { 433 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) {
404 error_ = kInvalidParameters; 434 error_ = kInvalidParameters;
405 return false; 435 return false;
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 initial_path_ = documents_dir.Append(suggested_name); 650 initial_path_ = documents_dir.Append(suggested_name);
621 } else { 651 } else {
622 initial_path_ = suggested_name; 652 initial_path_ = suggested_name;
623 } 653 }
624 } 654 }
625 } 655 }
626 656
627 void FileSystemChooseEntryFunction::FilesSelected( 657 void FileSystemChooseEntryFunction::FilesSelected(
628 const std::vector<base::FilePath>& paths) { 658 const std::vector<base::FilePath>& paths) {
629 DCHECK(!paths.empty()); 659 DCHECK(!paths.empty());
630 file_system_api::SetLastChooseEntryDirectory( 660 base::FilePath last_choose_directory;
631 ExtensionPrefs::Get(profile()), GetExtension()->id(), paths[0].DirName()); 661 if (is_directory_) {
662 last_choose_directory = paths[0];
663 } else {
664 last_choose_directory = paths[0].DirName();
665 }
666 file_system_api::SetLastChooseEntryDirectory(ExtensionPrefs::Get(profile()),
667 GetExtension()->id(),
668 last_choose_directory);
632 if (app_file_handler_util::HasFileSystemWritePermission(extension_)) { 669 if (app_file_handler_util::HasFileSystemWritePermission(extension_)) {
633 CheckWritableFiles(paths); 670 CheckWritableFiles(paths);
634 return; 671 return;
635 } 672 }
636 673
637 // Don't need to check the file, it's for reading. 674 // Don't need to check the file, it's for reading.
638 RegisterFileSystemsAndSendResponse(paths); 675 RegisterFileSystemsAndSendResponse(paths);
639 } 676 }
640 677
641 void FileSystemChooseEntryFunction::FileSelectionCanceled() { 678 void FileSystemChooseEntryFunction::FileSelectionCanceled() {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) { 762 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) {
726 if (!app_file_handler_util::HasFileSystemWritePermission(extension_)) { 763 if (!app_file_handler_util::HasFileSystemWritePermission(extension_)) {
727 error_ = kRequiresFileSystemWriteError; 764 error_ = kRequiresFileSystemWriteError;
728 return false; 765 return false;
729 } 766 }
730 if (multiple_) { 767 if (multiple_) {
731 error_ = kMultipleUnsupportedError; 768 error_ = kMultipleUnsupportedError;
732 return false; 769 return false;
733 } 770 }
734 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; 771 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
772 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) {
773 is_directory_ = true;
774 if (!extension_->HasAPIPermission(APIPermission::kFileSystemDirectory)) {
775 error_ = kRequiresFileSystemDirectoryError;
776 return false;
777 }
778 if (multiple_) {
779 error_ = kMultipleUnsupportedError;
780 return false;
781 }
782 picker_type = ui::SelectFileDialog::SELECT_FOLDER;
735 } 783 }
736 784
737 base::FilePath::StringType suggested_extension; 785 base::FilePath::StringType suggested_extension;
738 BuildSuggestion(options->suggested_name.get(), &suggested_name, 786 BuildSuggestion(options->suggested_name.get(), &suggested_name,
739 &suggested_extension); 787 &suggested_extension);
740 788
741 BuildFileTypeInfo(&file_type_info, suggested_extension, 789 BuildFileTypeInfo(&file_type_info, suggested_extension,
742 options->accepts.get(), options->accepts_all_types.get()); 790 options->accepts.get(), options->accepts_all_types.get());
743 } 791 }
744 792
(...skipping 15 matching lines...) Expand all
760 &FileSystemChooseEntryFunction::ShowPicker, this, file_type_info, 808 &FileSystemChooseEntryFunction::ShowPicker, this, file_type_info,
761 picker_type)); 809 picker_type));
762 return true; 810 return true;
763 } 811 }
764 812
765 bool FileSystemRetainEntryFunction::RunImpl() { 813 bool FileSystemRetainEntryFunction::RunImpl() {
766 std::string entry_id; 814 std::string entry_id;
767 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 815 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
768 SavedFilesService* saved_files_service = SavedFilesService::Get(profile()); 816 SavedFilesService* saved_files_service = SavedFilesService::Get(profile());
769 // Add the file to the retain list if it is not already on there. 817 // Add the file to the retain list if it is not already on there.
770 if (!saved_files_service->IsRegistered(extension_->id(), entry_id) && 818 if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) {
771 !RetainFileEntry(entry_id)) { 819 std::string filesystem_name;
772 return false; 820 std::string filesystem_path;
821 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name));
822 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path));
823 if (!ValidateFileEntryAndGetPath(filesystem_name,
824 filesystem_path,
825 render_view_host_,
826 &path_,
827 &error_)) {
828 return false;
829 }
830
831 content::BrowserThread::PostTaskAndReply(
832 content::BrowserThread::FILE,
833 FROM_HERE,
834 base::Bind(&FileSystemRetainEntryFunction::SetIsDirectoryOnFileThread,
835 this),
836 base::Bind(
837 &FileSystemRetainEntryFunction::RetainFileEntry, this, entry_id));
838 return true;
773 } 839 }
840
774 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); 841 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id);
842 SendResponse(true);
775 return true; 843 return true;
776 } 844 }
777 845
778 bool FileSystemRetainEntryFunction::RetainFileEntry( 846 void FileSystemRetainEntryFunction::RetainFileEntry(
779 const std::string& entry_id) { 847 const std::string& entry_id) {
780 std::string filesystem_name; 848 SavedFilesService* saved_files_service = SavedFilesService::Get(profile());
781 std::string filesystem_path; 849 saved_files_service->RegisterFileEntry(
782 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); 850 extension_->id(), entry_id, path_, is_directory_);
783 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); 851 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id);
784 base::FilePath path; 852 SendResponse(true);
785 if (!ValidateFileEntryAndGetPath(filesystem_name, 853 }
786 filesystem_path, 854
787 render_view_host_, 855 void FileSystemRetainEntryFunction::SetIsDirectoryOnFileThread() {
788 &path, 856 if (base::DirectoryExists(path_)) {
789 &error_)) { 857 is_directory_ = true;
790 return false;
791 } 858 }
792
793 SavedFilesService::Get(profile())->RegisterFileEntry(
794 extension_->id(), entry_id, path);
795 return true;
796 } 859 }
797 860
798 bool FileSystemIsRestorableFunction::RunImpl() { 861 bool FileSystemIsRestorableFunction::RunImpl() {
799 std::string entry_id; 862 std::string entry_id;
800 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 863 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
801 SetResult(new base::FundamentalValue(SavedFilesService::Get( 864 SetResult(new base::FundamentalValue(SavedFilesService::Get(
802 profile())->IsRegistered(extension_->id(), entry_id))); 865 profile())->IsRegistered(extension_->id(), entry_id)));
803 return true; 866 return true;
804 } 867 }
805 868
806 bool FileSystemRestoreEntryFunction::RunImpl() { 869 bool FileSystemRestoreEntryFunction::RunImpl() {
807 std::string entry_id; 870 std::string entry_id;
808 bool needs_new_entry; 871 bool needs_new_entry;
809 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 872 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
810 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry)); 873 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry));
811 const SavedFileEntry* file_entry = SavedFilesService::Get( 874 const SavedFileEntry* file_entry = SavedFilesService::Get(
812 profile())->GetFileEntry(extension_->id(), entry_id); 875 profile())->GetFileEntry(extension_->id(), entry_id);
813 if (!file_entry) { 876 if (!file_entry) {
814 error_ = kUnknownIdError; 877 error_ = kUnknownIdError;
815 return false; 878 return false;
816 } 879 }
817 880
818 SavedFilesService::Get(profile())->EnqueueFileEntry( 881 SavedFilesService::Get(profile())->EnqueueFileEntry(
819 extension_->id(), entry_id); 882 extension_->id(), entry_id);
820 883
821 // Only create a new file entry if the renderer requests one. 884 // Only create a new file entry if the renderer requests one.
822 // |needs_new_entry| will be false if the renderer already has an Entry for 885 // |needs_new_entry| will be false if the renderer already has an Entry for
823 // |entry_id|. 886 // |entry_id|.
824 if (needs_new_entry) { 887 if (needs_new_entry) {
888 is_directory_ = file_entry->is_directory;
825 CreateResponse(); 889 CreateResponse();
826 AddEntryToResponse(file_entry->path, file_entry->id); 890 AddEntryToResponse(file_entry->path, file_entry->id);
827 } 891 }
828 SendResponse(true); 892 SendResponse(true);
829 return true; 893 return true;
830 } 894 }
831 895
832 } // namespace extensions 896 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698