Index: chrome/browser/extensions/api/file_system/file_system_api.cc |
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc |
index 43c69a19a22a655502bb8bf03ab46282c2b4a3ef..4e3de965185b8f5a73a35631c784fb2e00f5f2ff 100644 |
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc |
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc |
@@ -60,6 +60,8 @@ const char kUserCancelled[] = "User cancelled"; |
const char kWritableFileErrorFormat[] = "Error opening %s"; |
const char kRequiresFileSystemWriteError[] = |
"Operation requires fileSystem.write permission"; |
+const char kRequiresFileSystemDirectoryError[] = |
+ "Operation requires fileSystem.directory permission"; |
const char kMultipleUnsupportedError[] = |
"acceptsMultiple: true is not supported for 'saveFile'"; |
const char kUnknownIdError[] = "Unknown id"; |
@@ -304,6 +306,7 @@ bool FileSystemGetDisplayPathFunction::RunImpl() { |
FileSystemEntryFunction::FileSystemEntryFunction() |
: multiple_(false), |
+ is_directory_(false), |
response_(NULL) {} |
void FileSystemEntryFunction::CheckWritableFiles( |
@@ -312,6 +315,7 @@ void FileSystemEntryFunction::CheckWritableFiles( |
app_file_handler_util::CheckWritableFiles( |
paths, |
profile_, |
+ is_directory_, |
base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse, |
this, |
paths), |
@@ -348,7 +352,8 @@ void FileSystemEntryFunction::AddEntryToResponse( |
profile(), |
GetExtension(), |
render_view_host_->GetProcess()->GetID(), |
- path); |
+ path, |
+ is_directory_); |
base::ListValue* entries; |
bool success = response_->GetList("entries", &entries); |
DCHECK(success); |
@@ -360,6 +365,7 @@ void FileSystemEntryFunction::AddEntryToResponse( |
entry->SetString("id", file_entry.id); |
else |
entry->SetString("id", id_override); |
+ entry->SetBoolean("isDirectory", is_directory_); |
entries->Append(entry); |
} |
@@ -382,15 +388,39 @@ bool FileSystemGetWritableEntryFunction::RunImpl() { |
return false; |
} |
- base::FilePath path; |
if (!ValidateFileEntryAndGetPath(filesystem_name, filesystem_path, |
- render_view_host_, &path, &error_)) |
+ render_view_host_, &path_, &error_)) |
return false; |
+ content::BrowserThread::PostTaskAndReply( |
+ content::BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind( |
+ &FileSystemGetWritableEntryFunction::SetIsDirectoryOnFileThread, |
+ this), |
+ base::Bind( |
+ &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse, |
+ this)); |
+ return true; |
+} |
+ |
+void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ if (is_directory_ && |
+ !extension_->HasAPIPermission(APIPermission::kFileSystemDirectory)) { |
+ error_ = kRequiresFileSystemDirectoryError; |
+ SendResponse(false); |
+ } |
std::vector<base::FilePath> paths; |
- paths.push_back(path); |
+ paths.push_back(path_); |
CheckWritableFiles(paths); |
- return true; |
+} |
+ |
+void FileSystemGetWritableEntryFunction::SetIsDirectoryOnFileThread() { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ if (base::DirectoryExists(path_)) { |
+ is_directory_ = true; |
+ } |
} |
bool FileSystemIsWritableEntryFunction::RunImpl() { |
@@ -627,8 +657,15 @@ void FileSystemChooseEntryFunction::SetInitialPathOnFileThread( |
void FileSystemChooseEntryFunction::FilesSelected( |
const std::vector<base::FilePath>& paths) { |
DCHECK(!paths.empty()); |
- file_system_api::SetLastChooseEntryDirectory( |
- ExtensionPrefs::Get(profile()), GetExtension()->id(), paths[0].DirName()); |
+ base::FilePath last_choose_directory; |
+ if (is_directory_) { |
+ last_choose_directory = paths[0]; |
+ } else { |
+ last_choose_directory = paths[0].DirName(); |
+ } |
+ file_system_api::SetLastChooseEntryDirectory(ExtensionPrefs::Get(profile()), |
+ GetExtension()->id(), |
+ last_choose_directory); |
if (app_file_handler_util::HasFileSystemWritePermission(extension_)) { |
CheckWritableFiles(paths); |
return; |
@@ -732,6 +769,17 @@ bool FileSystemChooseEntryFunction::RunImpl() { |
return false; |
} |
picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; |
+ } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) { |
+ is_directory_ = true; |
+ if (!extension_->HasAPIPermission(APIPermission::kFileSystemDirectory)) { |
+ error_ = kRequiresFileSystemDirectoryError; |
+ return false; |
+ } |
+ if (multiple_) { |
+ error_ = kMultipleUnsupportedError; |
+ return false; |
+ } |
+ picker_type = ui::SelectFileDialog::SELECT_FOLDER; |
} |
base::FilePath::StringType suggested_extension; |
@@ -767,32 +815,47 @@ bool FileSystemRetainEntryFunction::RunImpl() { |
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); |
SavedFilesService* saved_files_service = SavedFilesService::Get(profile()); |
// Add the file to the retain list if it is not already on there. |
- if (!saved_files_service->IsRegistered(extension_->id(), entry_id) && |
- !RetainFileEntry(entry_id)) { |
- return false; |
+ if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) { |
+ std::string filesystem_name; |
+ std::string filesystem_path; |
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); |
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); |
+ if (!ValidateFileEntryAndGetPath(filesystem_name, |
+ filesystem_path, |
+ render_view_host_, |
+ &path_, |
+ &error_)) { |
+ return false; |
+ } |
+ |
+ content::BrowserThread::PostTaskAndReply( |
+ content::BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&FileSystemRetainEntryFunction::SetIsDirectoryOnFileThread, |
+ this), |
+ base::Bind( |
+ &FileSystemRetainEntryFunction::RetainFileEntry, this, entry_id)); |
+ return true; |
} |
+ |
saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); |
+ SendResponse(true); |
return true; |
} |
-bool FileSystemRetainEntryFunction::RetainFileEntry( |
+void FileSystemRetainEntryFunction::RetainFileEntry( |
const std::string& entry_id) { |
- std::string filesystem_name; |
- std::string filesystem_path; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); |
- base::FilePath path; |
- if (!ValidateFileEntryAndGetPath(filesystem_name, |
- filesystem_path, |
- render_view_host_, |
- &path, |
- &error_)) { |
- return false; |
- } |
+ SavedFilesService* saved_files_service = SavedFilesService::Get(profile()); |
+ saved_files_service->RegisterFileEntry( |
+ extension_->id(), entry_id, path_, is_directory_); |
+ saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); |
+ SendResponse(true); |
+} |
- SavedFilesService::Get(profile())->RegisterFileEntry( |
- extension_->id(), entry_id, path); |
- return true; |
+void FileSystemRetainEntryFunction::SetIsDirectoryOnFileThread() { |
+ if (base::DirectoryExists(path_)) { |
+ is_directory_ = true; |
+ } |
} |
bool FileSystemIsRestorableFunction::RunImpl() { |
@@ -822,6 +885,7 @@ bool FileSystemRestoreEntryFunction::RunImpl() { |
// |needs_new_entry| will be false if the renderer already has an Entry for |
// |entry_id|. |
if (needs_new_entry) { |
+ is_directory_ = file_entry->is_directory; |
CreateResponse(); |
AddEntryToResponse(file_entry->path, file_entry->id); |
} |