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

Unified Diff: chrome/browser/extensions/api/file_system/file_system_api.cc

Issue 10534156: Implement fileSystem.chooseFile. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback Created 8 years, 6 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 side-by-side diff with in-line comments
Download patch
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 bbf689e4c2f243d10136c6ae1e1ae1563a124e38..a091e04390e9f33d738c78cc64f6500527d34e78 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -4,11 +4,14 @@
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
+#include "base/bind.h"
#include "base/file_path.h"
+#include "base/file_util.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/browser/ui/select_file_dialog.h"
+#include "chrome/common/extensions/api/file_system.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_process_host.h"
@@ -20,6 +23,12 @@ const char kInvalidParameters[] = "Invalid parameters";
const char kSecurityError[] = "Security error";
const char kInvalidCallingPage[] = "Invalid calling page";
const char kUserCancelled[] = "User cancelled";
+const char kWritableFileError[] = "Invalid file for writing";
+
+const char kSaveFileOption[] = "saveFile";
+
+namespace file_system = extensions::api::file_system;
+namespace ChooseFile = file_system::ChooseFile;
namespace {
@@ -59,6 +68,20 @@ bool GetFilePathOfFileEntry(const std::string& filesystem_name,
return true;
}
+bool DoCheckWritableFile(const FilePath& path) {
+ // Don't allow links.
+ if (file_util::PathExists(path) && file_util::IsLink(path))
+ return false;
+
+ // Create the file if it doesn't already exist.
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ int creation_flags = base::PLATFORM_FILE_CREATE |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE;
+ base::CreatePlatformFile(path, creation_flags, NULL, &error);
+ return error == base::PLATFORM_FILE_OK;
+}
+
} // namespace
namespace extensions {
@@ -81,13 +104,14 @@ bool FileSystemGetDisplayPathFunction::RunImpl() {
// Handles showing a dialog to the user to ask for the filename for a file to
// save.
-class FileSystemGetWritableFileEntryFunction::FilePicker
- : public SelectFileDialog::Listener {
+class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener {
public:
- FilePicker(FileSystemGetWritableFileEntryFunction* function,
+ FilePicker(FileSystemPickerFunction* function,
content::WebContents* web_contents,
- const FilePath& suggested_path)
+ const FilePath& suggested_path,
+ bool for_save)
: suggested_path_(suggested_path),
+ for_save_(for_save),
function_(function) {
select_file_dialog_ = SelectFileDialog::Create(this);
SelectFileDialog::FileTypeInfo file_type_info;
@@ -101,7 +125,9 @@ class FileSystemGetWritableFileEntryFunction::FilePicker
gfx::NativeWindow owning_window = web_contents ?
platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL;
- select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE,
+ select_file_dialog_->SelectFile(for_save ?
+ SelectFileDialog::SELECT_SAVEAS_FILE :
+ SelectFileDialog::SELECT_OPEN_FILE,
string16(),
suggested_path,
&file_type_info, 0, FILE_PATH_LITERAL(""),
@@ -115,7 +141,7 @@ class FileSystemGetWritableFileEntryFunction::FilePicker
virtual void FileSelected(const FilePath& path,
int index,
void* params) OVERRIDE {
- function_->FileSelected(path);
+ function_->FileSelected(path, for_save_);
delete this;
}
@@ -126,25 +152,19 @@ class FileSystemGetWritableFileEntryFunction::FilePicker
FilePath suggested_path_;
- // For managing select file dialogs.
+ // for_save_ is false when using the picker to open a file, and true
+ // when saving. It affects the style of the dialog and also what happens
+ // after a file is selected by the user.
+ bool for_save_;
+
scoped_refptr<SelectFileDialog> select_file_dialog_;
- scoped_refptr<FileSystemGetWritableFileEntryFunction> function_;
+ scoped_refptr<FileSystemPickerFunction> function_;
DISALLOW_COPY_AND_ASSIGN(FilePicker);
};
-bool FileSystemGetWritableFileEntryFunction::RunImpl() {
- std::string filesystem_name;
- std::string filesystem_path;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
-
- FilePath suggested_path;
- if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
- render_view_host_, &suggested_path, &error_)) {
- return false;
- }
-
+bool FileSystemPickerFunction::ShowPicker(const FilePath& suggested_path,
+ bool for_save) {
ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
DCHECK(registry);
ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
@@ -158,12 +178,43 @@ bool FileSystemGetWritableFileEntryFunction::RunImpl() {
// its destruction (and subsequent sending of the function response) until the
// user has selected a file or cancelled the picker. At that point, the picker
// will delete itself, which will also free the function instance.
- new FilePicker(this, shell_window->web_contents(), suggested_path);
+ new FilePicker(this, shell_window->web_contents(), suggested_path, for_save);
return true;
}
-void FileSystemGetWritableFileEntryFunction::FileSelected(
- const FilePath& path) {
+void FileSystemPickerFunction::FileSelected(const FilePath& path,
+ bool for_save) {
+ if (for_save) {
+ content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(&FileSystemPickerFunction::CheckWritableFile, this, path));
+ return;
+ }
+
+ // Don't need to check the file, it's for reading.
+ RegisterFileSystemAndSendResponse(path, false);
+}
+
+void FileSystemPickerFunction::FileSelectionCanceled() {
+ error_ = kUserCancelled;
+ SendResponse(false);
+}
+
+void FileSystemPickerFunction::CheckWritableFile(const FilePath& path) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ if (DoCheckWritableFile(path)) {
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&FileSystemPickerFunction::RegisterFileSystemAndSendResponse,
+ this, path, true));
+ return;
+ }
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&FileSystemPickerFunction::HandleWritableFileError, this));
+}
+
+void FileSystemPickerFunction::RegisterFileSystemAndSendResponse(
+ const FilePath& path, bool for_save) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
std::set<FilePath> filesets;
filesets.insert(path);
@@ -176,7 +227,16 @@ void FileSystemGetWritableFileEntryFunction::FileSelected(
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
int renderer_id = render_view_host_->GetProcess()->GetID();
- policy->GrantReadWriteFileSystem(renderer_id, filesystem_id);
+ if (for_save)
+ policy->GrantReadWriteFileSystem(renderer_id, filesystem_id);
+ else
+ policy->GrantReadFileSystem(renderer_id, filesystem_id);
+
+ // We only need file level access for reading FileEntries. Saving FileEntries
+ // just needs the file system to have read/write access, which is granted
+ // above if required.
+ if (!policy->CanReadFile(renderer_id, path))
+ policy->GrantReadFile(renderer_id, path);
DictionaryValue* dict = new DictionaryValue();
result_.reset(dict);
@@ -185,9 +245,39 @@ void FileSystemGetWritableFileEntryFunction::FileSelected(
SendResponse(true);
}
-void FileSystemGetWritableFileEntryFunction::FileSelectionCanceled() {
- error_ = kUserCancelled;
+void FileSystemPickerFunction::HandleWritableFileError() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ error_ = kWritableFileError;
SendResponse(false);
}
+bool FileSystemGetWritableFileEntryFunction::RunImpl() {
+ std::string filesystem_name;
+ std::string filesystem_path;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
+
+ FilePath suggested_path;
+ if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
+ render_view_host_, &suggested_path, &error_)) {
+ return false;
+ }
+
+ return ShowPicker(suggested_path, true);
+}
+
+bool FileSystemChooseFileFunction::RunImpl() {
+ scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ bool for_save = false;
+ file_system::ChooseFileOptions* options = params->options.get();
+ if (options) {
+ if (options->type.get() && *options->type == kSaveFileOption)
Mihai Parparita -not on Chrome 2012/06/15 04:19:15 Nit: extra space before the *
+ for_save = true;
+ }
+
+ return ShowPicker(FilePath(), for_save);
+}
+
} // namespace extensions
« no previous file with comments | « chrome/browser/extensions/api/file_system/file_system_api.h ('k') | chrome/common/extensions/api/file_system.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698