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

Side by Side 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: Cleanup 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 unified diff | Download patch | Annotate | Revision Log
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 "base/bind.h"
7 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #include "base/file_util.h"
8 #include "chrome/browser/extensions/shell_window_registry.h" 10 #include "chrome/browser/extensions/shell_window_registry.h"
9 #include "chrome/browser/platform_util.h" 11 #include "chrome/browser/platform_util.h"
10 #include "chrome/browser/ui/extensions/shell_window.h" 12 #include "chrome/browser/ui/extensions/shell_window.h"
11 #include "chrome/browser/ui/select_file_dialog.h" 13 #include "chrome/browser/ui/select_file_dialog.h"
14 #include "chrome/common/extensions/api/file_system.h"
12 #include "content/public/browser/child_process_security_policy.h" 15 #include "content/public/browser/child_process_security_policy.h"
13 #include "content/public/browser/render_view_host.h" 16 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/render_process_host.h" 17 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/web_contents.h" 18 #include "content/public/browser/web_contents.h"
16 #include "webkit/fileapi/file_system_util.h" 19 #include "webkit/fileapi/file_system_util.h"
17 #include "webkit/fileapi/isolated_context.h" 20 #include "webkit/fileapi/isolated_context.h"
18 21
19 const char kInvalidParameters[] = "Invalid parameters"; 22 const char kInvalidParameters[] = "Invalid parameters";
20 const char kSecurityError[] = "Security error"; 23 const char kSecurityError[] = "Security error";
21 const char kInvalidCallingPage[] = "Invalid calling page"; 24 const char kInvalidCallingPage[] = "Invalid calling page";
22 const char kUserCancelled[] = "User cancelled"; 25 const char kUserCancelled[] = "User cancelled";
26 const char kWritableFileError[] = "Invalid file for writing";
27
28 const char kSaveFileOption[] = "saveFile";
29
30 namespace file_system = extensions::api::file_system;
31 namespace ChooseFile = file_system::ChooseFile;
23 32
24 namespace { 33 namespace {
25 34
26 bool GetFilePathOfFileEntry(const std::string& filesystem_name, 35 bool GetFilePathOfFileEntry(const std::string& filesystem_name,
27 const std::string& filesystem_path, 36 const std::string& filesystem_path,
28 const content::RenderViewHost* render_view_host, 37 const content::RenderViewHost* render_view_host,
29 FilePath* file_path, 38 FilePath* file_path,
30 std::string* error) { 39 std::string* error) {
31 std::string filesystem_id; 40 std::string filesystem_id;
32 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) { 41 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) {
(...skipping 19 matching lines...) Expand all
52 &filesystem_id, 61 &filesystem_id,
53 NULL, 62 NULL,
54 file_path)) { 63 file_path)) {
55 *error = kInvalidParameters; 64 *error = kInvalidParameters;
56 return false; 65 return false;
57 } 66 }
58 67
59 return true; 68 return true;
60 } 69 }
61 70
71 bool DoCheckWritableFile(const FilePath& path) {
72 // Don't allow links.
73 if (file_util::PathExists(path) && file_util::IsLink(path))
74 return false;
75
76 // Create the file if it doesn't already exist.
77 bool created = false;
koz (OOO until 15th September) 2012/06/14 06:18:01 This doesn't seem to be used, so you can remove it
benwells 2012/06/15 00:45:44 Done. I also changed from CREATE_ALWAYS to CREATE,
78 base::PlatformFileError error = base::PLATFORM_FILE_OK;
79 int creation_flags = base::PLATFORM_FILE_CREATE_ALWAYS |
80 base::PLATFORM_FILE_READ |
81 base::PLATFORM_FILE_WRITE;
82 base::CreatePlatformFile(path, creation_flags, &created, &error);
83 return error == base::PLATFORM_FILE_OK;
84 }
85
62 } // namespace 86 } // namespace
63 87
64 namespace extensions { 88 namespace extensions {
65 89
66 bool FileSystemGetDisplayPathFunction::RunImpl() { 90 bool FileSystemGetDisplayPathFunction::RunImpl() {
67 std::string filesystem_name; 91 std::string filesystem_name;
68 std::string filesystem_path; 92 std::string filesystem_path;
69 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 93 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
70 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 94 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
71 95
72 FilePath file_path; 96 FilePath file_path;
73 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, 97 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
74 render_view_host_, &file_path, &error_)) { 98 render_view_host_, &file_path, &error_)) {
75 return false; 99 return false;
76 } 100 }
77 101
78 result_.reset(base::Value::CreateStringValue(file_path.value())); 102 result_.reset(base::Value::CreateStringValue(file_path.value()));
79 return true; 103 return true;
80 } 104 }
81 105
82 // Handles showing a dialog to the user to ask for the filename for a file to 106 // Handles showing a dialog to the user to ask for the filename for a file to
83 // save. 107 // save.
84 class FileSystemGetWritableFileEntryFunction::FilePicker 108 class FileSystemPickerFunction::FilePicker : public SelectFileDialog::Listener {
85 : public SelectFileDialog::Listener {
86 public: 109 public:
87 FilePicker(FileSystemGetWritableFileEntryFunction* function, 110 FilePicker(FileSystemPickerFunction* function,
88 content::WebContents* web_contents, 111 content::WebContents* web_contents,
89 const FilePath& suggested_path) 112 const FilePath& suggested_path,
113 bool for_save)
90 : suggested_path_(suggested_path), 114 : suggested_path_(suggested_path),
115 for_save_(for_save),
91 function_(function) { 116 function_(function) {
92 select_file_dialog_ = SelectFileDialog::Create(this); 117 select_file_dialog_ = SelectFileDialog::Create(this);
93 SelectFileDialog::FileTypeInfo file_type_info; 118 SelectFileDialog::FileTypeInfo file_type_info;
94 FilePath::StringType extension = suggested_path.Extension(); 119 FilePath::StringType extension = suggested_path.Extension();
95 if (!extension.empty()) { 120 if (!extension.empty()) {
96 extension.erase(extension.begin()); // drop the . 121 extension.erase(extension.begin()); // drop the .
97 file_type_info.extensions.resize(1); 122 file_type_info.extensions.resize(1);
98 file_type_info.extensions[0].push_back(extension); 123 file_type_info.extensions[0].push_back(extension);
99 } 124 }
100 file_type_info.include_all_files = true; 125 file_type_info.include_all_files = true;
101 gfx::NativeWindow owning_window = web_contents ? 126 gfx::NativeWindow owning_window = web_contents ?
102 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL; 127 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL;
103 128
104 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, 129 select_file_dialog_->SelectFile(for_save ?
130 SelectFileDialog::SELECT_SAVEAS_FILE :
131 SelectFileDialog::SELECT_OPEN_FILE,
105 string16(), 132 string16(),
106 suggested_path, 133 suggested_path,
107 &file_type_info, 0, FILE_PATH_LITERAL(""), 134 &file_type_info, 0, FILE_PATH_LITERAL(""),
108 web_contents, owning_window, NULL); 135 web_contents, owning_window, NULL);
109 } 136 }
110 137
111 virtual ~FilePicker() {} 138 virtual ~FilePicker() {}
112 139
113 private: 140 private:
114 // SelectFileDialog::Listener implementation. 141 // SelectFileDialog::Listener implementation.
115 virtual void FileSelected(const FilePath& path, 142 virtual void FileSelected(const FilePath& path,
116 int index, 143 int index,
117 void* params) OVERRIDE { 144 void* params) OVERRIDE {
118 function_->FileSelected(path); 145 function_->FileSelected(path, for_save_);
119 delete this; 146 delete this;
120 } 147 }
121 148
122 virtual void FileSelectionCanceled(void* params) OVERRIDE { 149 virtual void FileSelectionCanceled(void* params) OVERRIDE {
123 function_->FileSelectionCanceled(); 150 function_->FileSelectionCanceled();
124 delete this; 151 delete this;
125 } 152 }
126 153
127 FilePath suggested_path_; 154 FilePath suggested_path_;
155 bool for_save_;
koz (OOO until 15th September) 2012/06/14 06:18:01 Could you add a comment here?
benwells 2012/06/15 00:45:44 Done.
128 156
129 // For managing select file dialogs.
130 scoped_refptr<SelectFileDialog> select_file_dialog_; 157 scoped_refptr<SelectFileDialog> select_file_dialog_;
131 scoped_refptr<FileSystemGetWritableFileEntryFunction> function_; 158 scoped_refptr<FileSystemPickerFunction> function_;
132 159
133 DISALLOW_COPY_AND_ASSIGN(FilePicker); 160 DISALLOW_COPY_AND_ASSIGN(FilePicker);
134 }; 161 };
135 162
136 bool FileSystemGetWritableFileEntryFunction::RunImpl() { 163 bool FileSystemPickerFunction::ShowPicker(const FilePath& suggested_path,
137 std::string filesystem_name; 164 bool for_save) {
138 std::string filesystem_path;
139 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
140 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
141
142 FilePath suggested_path;
143 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
144 render_view_host_, &suggested_path, &error_)) {
145 return false;
146 }
147
148 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); 165 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
149 DCHECK(registry); 166 DCHECK(registry);
150 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( 167 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
151 render_view_host()); 168 render_view_host());
152 if (!shell_window) { 169 if (!shell_window) {
153 error_ = kInvalidCallingPage; 170 error_ = kInvalidCallingPage;
154 return false; 171 return false;
155 } 172 }
156 173
157 // The file picker will hold a reference to this function instance, preventing 174 // The file picker will hold a reference to this function instance, preventing
158 // its destruction (and subsequent sending of the function response) until the 175 // its destruction (and subsequent sending of the function response) until the
159 // user has selected a file or cancelled the picker. At that point, the picker 176 // user has selected a file or cancelled the picker. At that point, the picker
160 // will delete itself, which will also free the function instance. 177 // will delete itself, which will also free the function instance.
161 new FilePicker(this, shell_window->web_contents(), suggested_path); 178 new FilePicker(this, shell_window->web_contents(), suggested_path, for_save);
162 return true; 179 return true;
163 } 180 }
164 181
165 void FileSystemGetWritableFileEntryFunction::FileSelected( 182 void FileSystemPickerFunction::FileSelected(const FilePath& path,
166 const FilePath& path) { 183 bool for_save) {
184 if (for_save) {
185 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
186 base::Bind(&FileSystemPickerFunction::CheckWritableFile, this, path));
187 return;
188 }
189
190 // Don't need to check the file, it's for reading.
191 RegisterFileSystemAndSendResponse(path, false);
192 }
193
194 void FileSystemPickerFunction::FileSelectionCanceled() {
195 error_ = kUserCancelled;
196 SendResponse(false);
197 }
198
199 void FileSystemPickerFunction::CheckWritableFile(const FilePath& path) {
200 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
201 if (DoCheckWritableFile(path)) {
202 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
203 base::Bind(&FileSystemPickerFunction::RegisterFileSystemAndSendResponse,
204 this, path, true));
205 return;
206 }
207
208 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
209 base::Bind(&FileSystemPickerFunction::HandleWritableFileError, this));
210 }
211
212 void FileSystemPickerFunction::RegisterFileSystemAndSendResponse(
213 const FilePath& path, bool for_save) {
214 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
167 std::set<FilePath> filesets; 215 std::set<FilePath> filesets;
168 filesets.insert(path); 216 filesets.insert(path);
169 217
170 fileapi::IsolatedContext* isolated_context = 218 fileapi::IsolatedContext* isolated_context =
171 fileapi::IsolatedContext::GetInstance(); 219 fileapi::IsolatedContext::GetInstance();
172 DCHECK(isolated_context); 220 DCHECK(isolated_context);
173 std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem( 221 std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem(
174 filesets); 222 filesets);
175 223
176 content::ChildProcessSecurityPolicy* policy = 224 content::ChildProcessSecurityPolicy* policy =
177 content::ChildProcessSecurityPolicy::GetInstance(); 225 content::ChildProcessSecurityPolicy::GetInstance();
178 int renderer_id = render_view_host_->GetProcess()->GetID(); 226 int renderer_id = render_view_host_->GetProcess()->GetID();
179 policy->GrantReadWriteFileSystem(renderer_id, filesystem_id); 227 if (for_save)
228 policy->GrantReadWriteFileSystem(renderer_id, filesystem_id);
229 else
230 policy->GrantReadFileSystem(renderer_id, filesystem_id);
231
232 // We only need file level access for reading FileEntries. Saving FileEntries
233 // just needs the file system to have read/write access, which is granted
234 // above if required.
235 if (!policy->CanReadFile(renderer_id, path))
236 policy->GrantReadFile(renderer_id, path);
180 237
181 DictionaryValue* dict = new DictionaryValue(); 238 DictionaryValue* dict = new DictionaryValue();
182 result_.reset(dict); 239 result_.reset(dict);
183 dict->SetString("fileSystemId", filesystem_id); 240 dict->SetString("fileSystemId", filesystem_id);
184 dict->SetString("baseName", path.BaseName().AsUTF8Unsafe()); 241 dict->SetString("baseName", path.BaseName().AsUTF8Unsafe());
185 SendResponse(true); 242 SendResponse(true);
186 } 243 }
187 244
188 void FileSystemGetWritableFileEntryFunction::FileSelectionCanceled() { 245 void FileSystemPickerFunction::HandleWritableFileError() {
189 error_ = kUserCancelled; 246 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
247 error_ = kWritableFileError;
190 SendResponse(false); 248 SendResponse(false);
191 } 249 }
192 250
251 bool FileSystemGetWritableFileEntryFunction::RunImpl() {
252 std::string filesystem_name;
253 std::string filesystem_path;
254 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
255 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
256
257 FilePath suggested_path;
258 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path,
259 render_view_host_, &suggested_path, &error_)) {
260 return false;
261 }
262
263 return ShowPicker(suggested_path, true);
264 }
265
266 bool FileSystemChooseFileFunction::RunImpl() {
267 scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_));
268 EXTENSION_FUNCTION_VALIDATE(params.get());
269
270 bool for_save = false;
271 file_system::ChooseFileOptions* options = params->options.get();
272 if (options) {
273 if (options->type.get() && *options->type == kSaveFileOption)
274 for_save = true;
275 }
276
277 return ShowPicker(FilePath(), for_save);
278 }
279
193 } // namespace extensions 280 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698