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

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

Issue 2934143002: Move chrome.fileSystem implementation to //extensions (Closed)
Patch Set: rebase Created 3 years, 5 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 "extensions/browser/api/file_system/file_system_api.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "apps/saved_files_service.h"
15 #include "base/bind.h" 14 #include "base/bind.h"
16 #include "base/callback.h"
17 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
18 #include "base/files/file_util.h" 16 #include "base/files/file_util.h"
19 #include "base/macros.h" 17 #include "base/macros.h"
20 #include "base/memory/ptr_util.h" 18 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/path_service.h" 21 #include "base/path_service.h"
22 #include "base/stl_util.h" 22 #include "base/stl_util.h"
23 #include "base/strings/string16.h"
23 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
25 #include "base/strings/sys_string_conversions.h"
26 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
27 #include "base/task_scheduler/post_task.h" 27 #include "base/task_scheduler/post_task.h"
28 #include "base/value_conversions.h" 28 #include "base/value_conversions.h"
29 #include "base/values.h" 29 #include "base/values.h"
30 #include "build/build_config.h" 30 #include "build/build_config.h"
31 #include "chrome/browser/extensions/api/file_system/file_entry_picker.h" 31 #include "content/public/browser/browser_context.h"
32 #include "chrome/browser/platform_util.h"
33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h"
35 #include "chrome/browser/ui/chrome_select_file_policy.h"
36 #include "chrome/common/chrome_paths.h"
37 #include "chrome/common/extensions/api/file_system.h"
38 #include "chrome/grit/generated_resources.h"
39 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
40 #include "content/public/browser/child_process_security_policy.h" 33 #include "content/public/browser/child_process_security_policy.h"
41 #include "content/public/browser/render_frame_host.h" 34 #include "content/public/browser/render_frame_host.h"
42 #include "content/public/browser/render_process_host.h" 35 #include "content/public/browser/render_process_host.h"
43 #include "content/public/browser/storage_partition.h" 36 #include "content/public/browser/storage_partition.h"
44 #include "content/public/browser/web_contents.h" 37 #include "content/public/browser/web_contents.h"
38 #include "extensions/browser/api/extensions_api_client.h"
45 #include "extensions/browser/api/file_handlers/app_file_handler_util.h" 39 #include "extensions/browser/api/file_handlers/app_file_handler_util.h"
40 #include "extensions/browser/api/file_system/file_system_delegate.h"
46 #include "extensions/browser/api/file_system/saved_file_entry.h" 41 #include "extensions/browser/api/file_system/saved_file_entry.h"
42 #include "extensions/browser/api/file_system/saved_files_service_interface.h"
47 #include "extensions/browser/app_window/app_window.h" 43 #include "extensions/browser/app_window/app_window.h"
48 #include "extensions/browser/app_window/app_window_registry.h" 44 #include "extensions/browser/app_window/app_window_registry.h"
49 #include "extensions/browser/extension_prefs.h" 45 #include "extensions/browser/extension_prefs.h"
50 #include "extensions/browser/extension_system.h"
51 #include "extensions/browser/extension_util.h" 46 #include "extensions/browser/extension_util.h"
52 #include "extensions/browser/granted_file_entry.h" 47 #include "extensions/browser/granted_file_entry.h"
53 #include "extensions/browser/path_util.h" 48 #include "extensions/browser/path_util.h"
49 #include "extensions/common/api/file_system.h"
54 #include "extensions/common/permissions/api_permission.h" 50 #include "extensions/common/permissions/api_permission.h"
55 #include "extensions/common/permissions/permissions_data.h" 51 #include "extensions/common/permissions/permissions_data.h"
56 #include "net/base/mime_util.h" 52 #include "net/base/mime_util.h"
57 #include "storage/browser/fileapi/external_mount_points.h" 53 #include "storage/browser/fileapi/external_mount_points.h"
54 #include "storage/browser/fileapi/file_system_context.h"
58 #include "storage/browser/fileapi/file_system_operation_runner.h" 55 #include "storage/browser/fileapi/file_system_operation_runner.h"
59 #include "storage/browser/fileapi/isolated_context.h" 56 #include "storage/browser/fileapi/isolated_context.h"
60 #include "storage/common/fileapi/file_system_types.h" 57 #include "storage/common/fileapi/file_system_types.h"
61 #include "storage/common/fileapi/file_system_util.h" 58 #include "storage/common/fileapi/file_system_util.h"
62 #include "ui/base/l10n/l10n_util.h" 59 #include "ui/base/l10n/l10n_util.h"
63 #include "ui/base/ui_base_types.h"
64 #include "ui/shell_dialogs/select_file_dialog.h" 60 #include "ui/shell_dialogs/select_file_dialog.h"
65 #include "ui/shell_dialogs/select_file_policy.h"
66 61
67 #if defined(OS_MACOSX) 62 #if defined(OS_MACOSX)
68 #include <CoreFoundation/CoreFoundation.h> 63 #include <CoreFoundation/CoreFoundation.h>
69 #include "base/mac/foundation_util.h" 64 #include "base/mac/foundation_util.h"
70 #endif 65 #endif
71 66
72 #if defined(OS_CHROMEOS) 67 #if defined(OS_CHROMEOS)
73 #include "base/strings/string16.h" 68 #include "extensions/browser/api/file_handlers/non_native_file_system_delegate.h "
74 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
75 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
76 #include "extensions/browser/event_router.h"
77 #include "extensions/browser/extension_registry.h"
78 #include "extensions/common/constants.h"
79 #include "url/url_constants.h"
80 #endif 69 #endif
81 70
82 using apps::SavedFilesService;
83 using storage::IsolatedContext; 71 using storage::IsolatedContext;
84 72
85 const char kInvalidCallingPage[] = 73 const char kInvalidCallingPage[] =
86 "Invalid calling page. " 74 "Invalid calling page. "
87 "This function can't be called from a background page."; 75 "This function can't be called from a background page.";
88 const char kUserCancelled[] = "User cancelled"; 76 const char kUserCancelled[] = "User cancelled";
89 const char kWritableFileErrorFormat[] = "Error opening %s"; 77 const char kWritableFileErrorFormat[] = "Error opening %s";
90 const char kRequiresFileSystemWriteError[] = 78 const char kRequiresFileSystemWriteError[] =
91 "Operation requires fileSystem.write permission"; 79 "Operation requires fileSystem.write permission";
92 const char kRequiresFileSystemDirectoryError[] = 80 const char kRequiresFileSystemDirectoryError[] =
93 "Operation requires fileSystem.directory permission"; 81 "Operation requires fileSystem.directory permission";
94 const char kMultipleUnsupportedError[] = 82 const char kMultipleUnsupportedError[] =
95 "acceptsMultiple: true is only supported for 'openFile'"; 83 "acceptsMultiple: true is only supported for 'openFile'";
96 const char kUnknownIdError[] = "Unknown id"; 84 const char kUnknownIdError[] = "Unknown id";
97
98 #if !defined(OS_CHROMEOS)
99 const char kNotSupportedOnCurrentPlatformError[] = 85 const char kNotSupportedOnCurrentPlatformError[] =
100 "Operation not supported on the current platform."; 86 "Operation not supported on the current platform.";
101 #else 87 const char kRetainEntryError[] = "Could not retain file entry.";
88
89 #if defined(OS_CHROMEOS)
102 const char kNotSupportedOnNonKioskSessionError[] = 90 const char kNotSupportedOnNonKioskSessionError[] =
103 "Operation only supported for kiosk apps running in a kiosk session."; 91 "Operation only supported for kiosk apps running in a kiosk session.";
104 const char kVolumeNotFoundError[] = "Volume not found.";
105 const char kSecurityError[] = "Security error.";
106 const char kConsentImpossible[] =
107 "Impossible to ask for user consent as there is no app window visible.";
108 #endif 92 #endif
109 93
110 namespace extensions { 94 namespace extensions {
111 95
112 namespace file_system = api::file_system; 96 namespace file_system = api::file_system;
113 namespace ChooseEntry = file_system::ChooseEntry; 97 namespace ChooseEntry = file_system::ChooseEntry;
114 98
115 namespace { 99 namespace {
116 100
117 bool g_skip_picker_for_test = false; 101 bool g_skip_picker_for_test = false;
(...skipping 17 matching lines...) Expand all
135 std::vector<std::string>* list = accept_option.mime_types.get(); 119 std::vector<std::string>* list = accept_option.mime_types.get();
136 bool valid_type = false; 120 bool valid_type = false;
137 for (std::vector<std::string>::const_iterator iter = list->begin(); 121 for (std::vector<std::string>::const_iterator iter = list->begin();
138 iter != list->end(); ++iter) { 122 iter != list->end(); ++iter) {
139 std::vector<base::FilePath::StringType> inner; 123 std::vector<base::FilePath::StringType> inner;
140 std::string accept_type = base::ToLowerASCII(*iter); 124 std::string accept_type = base::ToLowerASCII(*iter);
141 net::GetExtensionsForMimeType(accept_type, &inner); 125 net::GetExtensionsForMimeType(accept_type, &inner);
142 if (inner.empty()) 126 if (inner.empty())
143 continue; 127 continue;
144 128
145 if (valid_type) 129 if (valid_type) {
146 description_id = 0; // We already have an accept type with label; if 130 description_id = 0; // We already have an accept type with label; if
147 // we find another, give up and use the default. 131 // we find another, give up and use the default.
148 else if (accept_type == "image/*") 132 } else {
149 description_id = IDS_IMAGE_FILES; 133 FileSystemDelegate* delegate =
150 else if (accept_type == "audio/*") 134 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
151 description_id = IDS_AUDIO_FILES; 135 DCHECK(delegate);
152 else if (accept_type == "video/*") 136 description_id = delegate->GetDescriptionIdForAcceptType(accept_type);
153 description_id = IDS_VIDEO_FILES; 137 }
154 138
155 extension_set.insert(inner.begin(), inner.end()); 139 extension_set.insert(inner.begin(), inner.end());
156 valid_type = true; 140 valid_type = true;
157 } 141 }
158 } 142 }
159 143
160 if (accept_option.extensions.get()) { 144 if (accept_option.extensions.get()) {
161 std::vector<std::string>* list = accept_option.extensions.get(); 145 std::vector<std::string>* list = accept_option.extensions.get();
162 for (std::vector<std::string>::const_iterator iter = list->begin(); 146 for (std::vector<std::string>::const_iterator iter = list->begin();
163 iter != list->end(); ++iter) { 147 iter != list->end(); ++iter) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 content::WebContents* web_contents = 200 content::WebContents* web_contents =
217 content::WebContents::FromRenderFrameHost(render_frame_host); 201 content::WebContents::FromRenderFrameHost(render_frame_host);
218 // Check if there is an app window associated with the web contents; if not, 202 // Check if there is an app window associated with the web contents; if not,
219 // return null. 203 // return null.
220 return AppWindowRegistry::Get(browser_context) 204 return AppWindowRegistry::Get(browser_context)
221 ->GetAppWindowForWebContents(web_contents) 205 ->GetAppWindowForWebContents(web_contents)
222 ? web_contents 206 ? web_contents
223 : nullptr; 207 : nullptr;
224 } 208 }
225 209
226 #if defined(OS_CHROMEOS)
227 // Fills a list of volumes mounted in the system.
228 void FillVolumeList(Profile* profile,
229 std::vector<api::file_system::Volume>* result) {
230 file_manager::VolumeManager* const volume_manager =
231 file_manager::VolumeManager::Get(profile);
232 DCHECK(volume_manager);
233
234 const auto& volume_list = volume_manager->GetVolumeList();
235 // Convert volume_list to result_volume_list.
236 for (const auto& volume : volume_list) {
237 api::file_system::Volume result_volume;
238 result_volume.volume_id = volume->volume_id();
239 result_volume.writable = !volume->is_read_only();
240 result->push_back(std::move(result_volume));
241 }
242 }
243 #endif
244
245 // Creates and shows a SelectFileDialog, or returns false if the dialog could
246 // not be created.
247 bool ShowSelectFileDialog(
248 scoped_refptr<UIThreadExtensionFunction> extension_function,
249 ui::SelectFileDialog::Type type,
250 const base::FilePath& default_path,
251 const ui::SelectFileDialog::FileTypeInfo* file_types,
252 FileEntryPicker::FilesSelectedCallback files_selected_callback,
253 base::OnceClosure file_selection_canceled_callback) {
254 // TODO(asargent/benwells) - As a short term remediation for
255 // crbug.com/179010 we're adding the ability for a whitelisted extension to
256 // use this API since chrome.fileBrowserHandler.selectFile is ChromeOS-only.
257 // Eventually we'd like a better solution and likely this code will go back
258 // to being platform-app only.
259 content::WebContents* const web_contents =
260 extension_function->extension()->is_platform_app()
261 ? GetWebContentsForRenderFrameHost(
262 extension_function->browser_context(),
263 extension_function->render_frame_host())
264 : extension_function->GetAssociatedWebContents();
265 if (!web_contents)
266 return false;
267
268 // The file picker will hold a reference to the UIThreadExtensionFunction
269 // instance, preventing its destruction (and subsequent sending of the
270 // function response) until the user has selected a file or cancelled the
271 // picker. At that point, the picker will delete itself, which will also free
272 // the function instance.
273 new FileEntryPicker(web_contents, default_path, *file_types, type,
274 std::move(files_selected_callback),
275 std::move(file_selection_canceled_callback));
276 return true;
277 }
278
279 } // namespace 210 } // namespace
280 211
281 namespace file_system_api { 212 namespace file_system_api {
282 213
283 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, 214 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
284 const std::string& extension_id) { 215 const std::string& extension_id) {
285 base::FilePath path; 216 base::FilePath path;
286 std::string string_path; 217 std::string string_path;
287 if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory, 218 if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory,
288 &string_path)) { 219 &string_path)) {
289 path = base::FilePath::FromUTF8Unsafe(string_path); 220 path = base::FilePath::FromUTF8Unsafe(string_path);
290 } 221 }
291 return path; 222 return path;
292 } 223 }
293 224
294 void SetLastChooseEntryDirectory(ExtensionPrefs* prefs, 225 void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
295 const std::string& extension_id, 226 const std::string& extension_id,
296 const base::FilePath& path) { 227 const base::FilePath& path) {
297 prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory, 228 prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory,
298 base::CreateFilePathValue(path)); 229 base::CreateFilePathValue(path));
299 } 230 }
300 231
301 #if defined(OS_CHROMEOS)
302 void DispatchVolumeListChangeEvent(Profile* profile) {
303 DCHECK(profile);
304 EventRouter* const event_router = EventRouter::Get(profile);
305 if (!event_router) // Possible on shutdown.
306 return;
307
308 ExtensionRegistry* const registry = ExtensionRegistry::Get(profile);
309 if (!registry) // Possible on shutdown.
310 return;
311
312 ConsentProviderDelegate consent_provider_delegate(profile, nullptr);
313 ConsentProvider consent_provider(&consent_provider_delegate);
314 api::file_system::VolumeListChangedEvent event_args;
315 FillVolumeList(profile, &event_args.volumes);
316 for (const auto& extension : registry->enabled_extensions()) {
317 if (!consent_provider.IsGrantable(*extension.get()))
318 continue;
319 event_router->DispatchEventToExtension(
320 extension->id(),
321 base::MakeUnique<Event>(
322 events::FILE_SYSTEM_ON_VOLUME_LIST_CHANGED,
323 api::file_system::OnVolumeListChanged::kEventName,
324 api::file_system::OnVolumeListChanged::Create(event_args)));
325 }
326 }
327 #endif
328
329 } // namespace file_system_api 232 } // namespace file_system_api
330 233
331 #if defined(OS_CHROMEOS)
332 using file_system_api::ConsentProvider;
333 #endif
334
335 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() { 234 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() {
336 std::string filesystem_name; 235 std::string filesystem_name;
337 std::string filesystem_path; 236 std::string filesystem_path;
338 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 237 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
339 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 238 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
340 239
341 base::FilePath file_path; 240 base::FilePath file_path;
342 std::string error; 241 std::string error;
343 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 242 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
344 filesystem_name, filesystem_path, 243 filesystem_name, filesystem_path,
(...skipping 13 matching lines...) Expand all
358 const std::vector<base::FilePath>& paths) { 257 const std::vector<base::FilePath>& paths) {
359 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 258 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
360 // TODO(cmihail): Path directory set should be initialized only with the 259 // TODO(cmihail): Path directory set should be initialized only with the
361 // paths that are actually directories, but for now we will consider 260 // paths that are actually directories, but for now we will consider
362 // all paths directories in case is_directory_ is true, otherwise 261 // all paths directories in case is_directory_ is true, otherwise
363 // all paths files, as this was the previous logic. 262 // all paths files, as this was the previous logic.
364 std::set<base::FilePath> path_directory_set_ = 263 std::set<base::FilePath> path_directory_set_ =
365 is_directory_ ? std::set<base::FilePath>(paths.begin(), paths.end()) 264 is_directory_ ? std::set<base::FilePath>(paths.begin(), paths.end())
366 : std::set<base::FilePath>{}; 265 : std::set<base::FilePath>{};
367 app_file_handler_util::PrepareFilesForWritableApp( 266 app_file_handler_util::PrepareFilesForWritableApp(
368 paths, GetProfile(), path_directory_set_, 267 paths, browser_context(), path_directory_set_,
369 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse, 268 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse,
370 this, paths), 269 this, paths),
371 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this)); 270 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this));
372 } 271 }
373 272
374 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse( 273 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse(
375 const std::vector<base::FilePath>& paths) { 274 const std::vector<base::FilePath>& paths) {
376 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 275 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
377 if (!render_frame_host()) 276 if (!render_frame_host())
378 return; 277 return;
379 278
380 std::unique_ptr<base::DictionaryValue> result = CreateResult(); 279 std::unique_ptr<base::DictionaryValue> result = CreateResult();
381 for (const auto& path : paths) 280 for (const auto& path : paths)
382 AddEntryToResult(path, std::string(), result.get()); 281 AddEntryToResult(path, std::string(), result.get());
383 SetResult(std::move(result)); 282 Respond(OneArgument(std::move(result)));
384 SendResponse(true);
385 } 283 }
386 284
387 std::unique_ptr<base::DictionaryValue> FileSystemEntryFunction::CreateResult() { 285 std::unique_ptr<base::DictionaryValue> FileSystemEntryFunction::CreateResult() {
388 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 286 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
389 result->Set("entries", base::MakeUnique<base::ListValue>()); 287 result->Set("entries", base::MakeUnique<base::ListValue>());
390 result->SetBoolean("multiple", multiple_); 288 result->SetBoolean("multiple", multiple_);
391 return result; 289 return result;
392 } 290 }
393 291
394 void FileSystemEntryFunction::AddEntryToResult(const base::FilePath& path, 292 void FileSystemEntryFunction::AddEntryToResult(const base::FilePath& path,
395 const std::string& id_override, 293 const std::string& id_override,
396 base::DictionaryValue* result) { 294 base::DictionaryValue* result) {
397 GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry( 295 GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry(
398 GetProfile(), extension(), render_frame_host()->GetProcess()->GetID(), 296 browser_context(), extension(),
399 path, is_directory_); 297 render_frame_host()->GetProcess()->GetID(), path, is_directory_);
400 base::ListValue* entries; 298 base::ListValue* entries;
401 bool success = result->GetList("entries", &entries); 299 bool success = result->GetList("entries", &entries);
402 DCHECK(success); 300 DCHECK(success);
403 301
404 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue()); 302 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
405 entry->SetString("fileSystemId", file_entry.filesystem_id); 303 entry->SetString("fileSystemId", file_entry.filesystem_id);
406 entry->SetString("baseName", file_entry.registered_name); 304 entry->SetString("baseName", file_entry.registered_name);
407 if (id_override.empty()) 305 if (id_override.empty())
408 entry->SetString("id", file_entry.id); 306 entry->SetString("id", file_entry.id);
409 else 307 else
410 entry->SetString("id", id_override); 308 entry->SetString("id", id_override);
411 entry->SetBoolean("isDirectory", is_directory_); 309 entry->SetBoolean("isDirectory", is_directory_);
412 entries->Append(std::move(entry)); 310 entries->Append(std::move(entry));
413 } 311 }
414 312
415 void FileSystemEntryFunction::HandleWritableFileError( 313 void FileSystemEntryFunction::HandleWritableFileError(
416 const base::FilePath& error_path) { 314 const base::FilePath& error_path) {
417 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 315 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
418 error_ = base::StringPrintf(kWritableFileErrorFormat, 316 Respond(Error(base::StringPrintf(
419 error_path.BaseName().AsUTF8Unsafe().c_str()); 317 kWritableFileErrorFormat, error_path.BaseName().AsUTF8Unsafe().c_str())));
420 SendResponse(false);
421 } 318 }
422 319
423 bool FileSystemGetWritableEntryFunction::RunAsync() { 320 ExtensionFunction::ResponseAction FileSystemGetWritableEntryFunction::Run() {
424 std::string filesystem_name; 321 std::string filesystem_name;
425 std::string filesystem_path; 322 std::string filesystem_path;
426 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 323 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
427 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 324 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
428 325
429 if (!app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { 326 if (!app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
430 error_ = kRequiresFileSystemWriteError; 327 return RespondNow(Error(kRequiresFileSystemWriteError));
431 return false;
432 } 328 }
433 329
330 std::string error;
434 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 331 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
435 filesystem_name, filesystem_path, 332 filesystem_name, filesystem_path,
436 render_frame_host()->GetProcess()->GetID(), &path_, &error_)) 333 render_frame_host()->GetProcess()->GetID(), &path_, &error)) {
437 return false; 334 return RespondNow(Error(error));
335 }
438 336
439 base::PostTaskWithTraitsAndReply( 337 base::PostTaskWithTraitsAndReply(
440 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 338 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
441 base::BindOnce(&FileSystemGetWritableEntryFunction::SetIsDirectoryAsync, 339 base::BindOnce(&FileSystemGetWritableEntryFunction::SetIsDirectoryAsync,
442 this), 340 this),
443 base::BindOnce( 341 base::BindOnce(
444 &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse, 342 &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse,
445 this)); 343 this));
446 return true; 344 return RespondLater();
447 } 345 }
448 346
449 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() { 347 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() {
450 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 348 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
451 if (is_directory_ && !extension_->permissions_data()->HasAPIPermission( 349 if (is_directory_ && !extension_->permissions_data()->HasAPIPermission(
452 APIPermission::kFileSystemDirectory)) { 350 APIPermission::kFileSystemDirectory)) {
453 error_ = kRequiresFileSystemDirectoryError; 351 Respond(Error(kRequiresFileSystemDirectoryError));
454 SendResponse(false); 352 return;
455 } 353 }
456 std::vector<base::FilePath> paths; 354 std::vector<base::FilePath> paths;
457 paths.push_back(path_); 355 paths.push_back(path_);
458 PrepareFilesForWritableApp(paths); 356 PrepareFilesForWritableApp(paths);
459 } 357 }
460 358
461 void FileSystemGetWritableEntryFunction::SetIsDirectoryAsync() { 359 void FileSystemGetWritableEntryFunction::SetIsDirectoryAsync() {
462 if (base::DirectoryExists(path_)) { 360 if (base::DirectoryExists(path_)) {
463 is_directory_ = true; 361 is_directory_ = true;
464 } 362 }
(...skipping 13 matching lines...) Expand all
478 content::ChildProcessSecurityPolicy::GetInstance(); 376 content::ChildProcessSecurityPolicy::GetInstance();
479 int renderer_id = render_frame_host()->GetProcess()->GetID(); 377 int renderer_id = render_frame_host()->GetProcess()->GetID();
480 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id); 378 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id);
481 379
482 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable))); 380 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable)));
483 } 381 }
484 382
485 void FileSystemChooseEntryFunction::ShowPicker( 383 void FileSystemChooseEntryFunction::ShowPicker(
486 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 384 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
487 ui::SelectFileDialog::Type picker_type) { 385 ui::SelectFileDialog::Type picker_type) {
386 // TODO(michaelpg): Use the FileSystemDelegate to override functionality for
387 // tests instead of using global variables.
488 if (g_skip_picker_for_test) { 388 if (g_skip_picker_for_test) {
489 std::vector<base::FilePath> test_paths; 389 std::vector<base::FilePath> test_paths;
490 if (g_use_suggested_path_for_test) 390 if (g_use_suggested_path_for_test)
491 test_paths.push_back(initial_path_); 391 test_paths.push_back(initial_path_);
492 else if (g_path_to_be_picked_for_test) 392 else if (g_path_to_be_picked_for_test)
493 test_paths.push_back(*g_path_to_be_picked_for_test); 393 test_paths.push_back(*g_path_to_be_picked_for_test);
494 else if (g_paths_to_be_picked_for_test) 394 else if (g_paths_to_be_picked_for_test)
495 test_paths = *g_paths_to_be_picked_for_test; 395 test_paths = *g_paths_to_be_picked_for_test;
496 396
497 content::BrowserThread::PostTask( 397 content::BrowserThread::PostTask(
498 content::BrowserThread::UI, FROM_HERE, 398 content::BrowserThread::UI, FROM_HERE,
499 test_paths.size() > 0 399 test_paths.size() > 0
500 ? base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected, 400 ? base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected,
501 this, test_paths) 401 this, test_paths)
502 : base::BindOnce( 402 : base::BindOnce(
503 &FileSystemChooseEntryFunction::FileSelectionCanceled, this)); 403 &FileSystemChooseEntryFunction::FileSelectionCanceled, this));
504 return; 404 return;
505 } 405 }
506 406
407 FileSystemDelegate* delegate =
408 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
409 DCHECK(delegate);
410
507 // The callbacks passed to the dialog will retain references to this 411 // The callbacks passed to the dialog will retain references to this
508 // UIThreadExtenisonFunction, preventing its destruction (and subsequent 412 // UIThreadExtenisonFunction, preventing its destruction (and subsequent
509 // sending of the function response) until the user has selected a file or 413 // sending of the function response) until the user has selected a file or
510 // cancelled the picker. 414 // cancelled the picker.
511 if (!ShowSelectFileDialog( 415 if (!delegate->ShowSelectFileDialog(
512 this, picker_type, initial_path_, &file_type_info, 416 this, picker_type, initial_path_, &file_type_info,
513 base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected, this), 417 base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected, this),
514 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled, 418 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
515 this))) { 419 this))) {
516 error_ = kInvalidCallingPage; 420 Respond(Error(kInvalidCallingPage));
517 SendResponse(false);
518 } 421 }
519 } 422 }
520 423
521 // static 424 // static
522 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( 425 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
523 base::FilePath* path) { 426 base::FilePath* path) {
524 g_skip_picker_for_test = true; 427 g_skip_picker_for_test = true;
525 g_use_suggested_path_for_test = false; 428 g_use_suggested_path_for_test = false;
526 g_path_to_be_picked_for_test = path; 429 g_path_to_be_picked_for_test = path;
527 g_paths_to_be_picked_for_test = NULL; 430 g_paths_to_be_picked_for_test = NULL;
528 } 431 }
529 432
433 // static
530 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest( 434 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest(
531 std::vector<base::FilePath>* paths) { 435 std::vector<base::FilePath>* paths) {
532 g_skip_picker_for_test = true; 436 g_skip_picker_for_test = true;
533 g_use_suggested_path_for_test = false; 437 g_use_suggested_path_for_test = false;
534 g_paths_to_be_picked_for_test = paths; 438 g_paths_to_be_picked_for_test = paths;
535 } 439 }
536 440
537 // static 441 // static
538 void FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest() { 442 void FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest() {
539 g_skip_picker_for_test = true; 443 g_skip_picker_for_test = true;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 void FileSystemChooseEntryFunction::FilesSelected( 491 void FileSystemChooseEntryFunction::FilesSelected(
588 const std::vector<base::FilePath>& paths) { 492 const std::vector<base::FilePath>& paths) {
589 DCHECK(!paths.empty()); 493 DCHECK(!paths.empty());
590 base::FilePath last_choose_directory; 494 base::FilePath last_choose_directory;
591 if (is_directory_) { 495 if (is_directory_) {
592 last_choose_directory = paths[0]; 496 last_choose_directory = paths[0];
593 } else { 497 } else {
594 last_choose_directory = paths[0].DirName(); 498 last_choose_directory = paths[0].DirName();
595 } 499 }
596 file_system_api::SetLastChooseEntryDirectory( 500 file_system_api::SetLastChooseEntryDirectory(
597 ExtensionPrefs::Get(GetProfile()), extension()->id(), 501 ExtensionPrefs::Get(browser_context()), extension()->id(),
598 last_choose_directory); 502 last_choose_directory);
599 if (is_directory_) { 503 if (is_directory_) {
600 // Get the WebContents for the app window to be the parent window of the 504 // Get the WebContents for the app window to be the parent window of the
601 // confirmation dialog if necessary. 505 // confirmation dialog if necessary.
602 content::WebContents* const web_contents = 506 content::WebContents* const web_contents = GetWebContentsForRenderFrameHost(
603 GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()); 507 browser_context(), render_frame_host());
604 if (!web_contents) { 508 if (!web_contents) {
605 error_ = kInvalidCallingPage; 509 Respond(Error(kInvalidCallingPage));
606 SendResponse(false);
607 return; 510 return;
608 } 511 }
609 512
610 DCHECK_EQ(paths.size(), 1u); 513 DCHECK_EQ(paths.size(), 1u);
611 bool non_native_path = false; 514 bool non_native_path = false;
612 #if defined(OS_CHROMEOS) 515 #if defined(OS_CHROMEOS)
613 non_native_path = 516 NonNativeFileSystemDelegate* delegate =
614 file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), paths[0]); 517 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
518 non_native_path = delegate && delegate->IsUnderNonNativeLocalPath(
519 browser_context(), paths[0]);
615 #endif 520 #endif
616 521
617 base::PostTaskWithTraits( 522 base::PostTaskWithTraits(
618 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 523 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
619 base::BindOnce( 524 base::BindOnce(
620 &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this, 525 &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this,
621 non_native_path, paths, web_contents)); 526 non_native_path, paths, web_contents));
622 return; 527 return;
623 } 528 }
624 529
625 OnDirectoryAccessConfirmed(paths); 530 OnDirectoryAccessConfirmed(paths);
626 } 531 }
627 532
628 void FileSystemChooseEntryFunction::FileSelectionCanceled() { 533 void FileSystemChooseEntryFunction::FileSelectionCanceled() {
629 error_ = kUserCancelled; 534 Respond(Error(kUserCancelled));
630 SendResponse(false);
631 } 535 }
632 536
633 void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync( 537 void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
634 bool non_native_path, 538 bool non_native_path,
635 const std::vector<base::FilePath>& paths, 539 const std::vector<base::FilePath>& paths,
636 content::WebContents* web_contents) { 540 content::WebContents* web_contents) {
637 const base::FilePath check_path = 541 const base::FilePath check_path =
638 non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]); 542 non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
639 if (check_path.empty()) { 543 if (check_path.empty()) {
640 content::BrowserThread::PostTask( 544 content::BrowserThread::PostTask(
641 content::BrowserThread::UI, FROM_HERE, 545 content::BrowserThread::UI, FROM_HERE,
642 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled, 546 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
643 this)); 547 this));
644 return; 548 return;
645 } 549 }
646 550
647 for (size_t i = 0; i < arraysize(kGraylistedPaths); i++) { 551 for (size_t i = 0; i < arraysize(kGraylistedPaths); i++) {
648 base::FilePath graylisted_path; 552 base::FilePath graylisted_path;
649 if (PathService::Get(kGraylistedPaths[i], &graylisted_path) && 553 if (!PathService::Get(kGraylistedPaths[i], &graylisted_path))
650 (check_path == graylisted_path || 554 continue;
651 check_path.IsParent(graylisted_path))) { 555 if (check_path != graylisted_path && !check_path.IsParent(graylisted_path))
652 if (g_skip_directory_confirmation_for_test) { 556 continue;
653 if (g_allow_directory_access_for_test) {
654 break;
655 } else {
656 content::BrowserThread::PostTask(
657 content::BrowserThread::UI, FROM_HERE,
658 base::BindOnce(
659 &FileSystemChooseEntryFunction::FileSelectionCanceled, this));
660 }
661 return;
662 }
663 557
558 if (g_skip_directory_confirmation_for_test) {
559 if (g_allow_directory_access_for_test)
560 break;
664 content::BrowserThread::PostTask( 561 content::BrowserThread::PostTask(
665 content::BrowserThread::UI, FROM_HERE, 562 content::BrowserThread::UI, FROM_HERE,
666 base::BindOnce( 563 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
667 CreateDirectoryAccessConfirmationDialog, 564 this));
668 app_file_handler_util::HasFileSystemWritePermission(
669 extension_.get()),
670 base::UTF8ToUTF16(extension_->name()), web_contents,
671 base::Bind(
672 &FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
673 this, paths),
674 base::Bind(&FileSystemChooseEntryFunction::FileSelectionCanceled,
675 this)));
676 return; 565 return;
677 } 566 }
567
568 content::BrowserThread::PostTask(
569 content::BrowserThread::UI, FROM_HERE,
570 base::BindOnce(
571 &FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
572 this, paths, web_contents));
573 return;
678 } 574 }
679 575
680 content::BrowserThread::PostTask( 576 content::BrowserThread::PostTask(
681 content::BrowserThread::UI, FROM_HERE, 577 content::BrowserThread::UI, FROM_HERE,
682 base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed, 578 base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
683 this, paths)); 579 this, paths));
684 } 580 }
685 581
582 void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
583 const std::vector<base::FilePath>& paths,
584 content::WebContents* web_contents) {
585 if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
586 FileSelectionCanceled();
587 return;
588 }
589
590 FileSystemDelegate* delegate =
591 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
592 if (!delegate) {
593 Respond(Error(kNotSupportedOnCurrentPlatformError));
594 return;
595 }
596
597 delegate->ConfirmSensitiveDirectoryAccess(
598 app_file_handler_util::HasFileSystemWritePermission(extension_.get()),
599 base::UTF8ToUTF16(extension_->name()), web_contents,
600 base::Bind(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
601 this, paths),
602 base::Bind(&FileSystemChooseEntryFunction::FileSelectionCanceled, this));
603 }
604
686 void FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed( 605 void FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed(
687 const std::vector<base::FilePath>& paths) { 606 const std::vector<base::FilePath>& paths) {
688 if (app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { 607 if (app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
689 PrepareFilesForWritableApp(paths); 608 PrepareFilesForWritableApp(paths);
690 return; 609 return;
691 } 610 }
692 611
693 // Don't need to check the file, it's for reading. 612 // Don't need to check the file, it's for reading.
694 RegisterFileSystemsAndSendResponse(paths); 613 RegisterFileSystemsAndSendResponse(paths);
695 } 614 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 void FileSystemChooseEntryFunction::SetInitialPathAndShowPicker( 674 void FileSystemChooseEntryFunction::SetInitialPathAndShowPicker(
756 const base::FilePath& previous_path, 675 const base::FilePath& previous_path,
757 const base::FilePath& suggested_name, 676 const base::FilePath& suggested_name,
758 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 677 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
759 ui::SelectFileDialog::Type picker_type, 678 ui::SelectFileDialog::Type picker_type,
760 bool is_previous_path_directory) { 679 bool is_previous_path_directory) {
761 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 680 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
762 if (is_previous_path_directory) { 681 if (is_previous_path_directory) {
763 initial_path_ = previous_path.Append(suggested_name); 682 initial_path_ = previous_path.Append(suggested_name);
764 } else { 683 } else {
765 base::FilePath documents_dir; 684 FileSystemDelegate* delegate =
766 if (PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir)) { 685 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
767 initial_path_ = documents_dir.Append(suggested_name); 686 DCHECK(delegate);
768 } else { 687 const base::FilePath default_directory = delegate->GetDefaultDirectory();
688 if (!default_directory.empty())
689 initial_path_ = default_directory.Append(suggested_name);
690 else
769 initial_path_ = suggested_name; 691 initial_path_ = suggested_name;
770 }
771 } 692 }
772 ShowPicker(file_type_info, picker_type); 693 ShowPicker(file_type_info, picker_type);
773 } 694 }
774 695
775 bool FileSystemChooseEntryFunction::RunAsync() { 696 ExtensionFunction::ResponseAction FileSystemChooseEntryFunction::Run() {
776 std::unique_ptr<ChooseEntry::Params> params( 697 std::unique_ptr<ChooseEntry::Params> params(
777 ChooseEntry::Params::Create(*args_)); 698 ChooseEntry::Params::Create(*args_));
778 EXTENSION_FUNCTION_VALIDATE(params.get()); 699 EXTENSION_FUNCTION_VALIDATE(params.get());
779 700
780 base::FilePath suggested_name; 701 base::FilePath suggested_name;
781 ui::SelectFileDialog::FileTypeInfo file_type_info; 702 ui::SelectFileDialog::FileTypeInfo file_type_info;
782 ui::SelectFileDialog::Type picker_type = 703 ui::SelectFileDialog::Type picker_type =
783 ui::SelectFileDialog::SELECT_OPEN_FILE; 704 ui::SelectFileDialog::SELECT_OPEN_FILE;
784 705
785 file_system::ChooseEntryOptions* options = params->options.get(); 706 file_system::ChooseEntryOptions* options = params->options.get();
786 if (options) { 707 if (options) {
787 multiple_ = options->accepts_multiple && *options->accepts_multiple; 708 multiple_ = options->accepts_multiple && *options->accepts_multiple;
788 if (multiple_) 709 if (multiple_)
789 picker_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE; 710 picker_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE;
790 711
791 if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENWRITABLEFILE && 712 if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENWRITABLEFILE &&
792 !app_file_handler_util::HasFileSystemWritePermission( 713 !app_file_handler_util::HasFileSystemWritePermission(
793 extension_.get())) { 714 extension_.get())) {
794 error_ = kRequiresFileSystemWriteError; 715 return RespondNow(Error(kRequiresFileSystemWriteError));
795 return false;
796 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) { 716 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) {
797 if (!app_file_handler_util::HasFileSystemWritePermission( 717 if (!app_file_handler_util::HasFileSystemWritePermission(
798 extension_.get())) { 718 extension_.get())) {
799 error_ = kRequiresFileSystemWriteError; 719 return RespondNow(Error(kRequiresFileSystemWriteError));
800 return false;
801 } 720 }
802 if (multiple_) { 721 if (multiple_) {
803 error_ = kMultipleUnsupportedError; 722 return RespondNow(Error(kMultipleUnsupportedError));
804 return false;
805 } 723 }
806 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; 724 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
807 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) { 725 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) {
808 is_directory_ = true; 726 is_directory_ = true;
809 if (!extension_->permissions_data()->HasAPIPermission( 727 if (!extension_->permissions_data()->HasAPIPermission(
810 APIPermission::kFileSystemDirectory)) { 728 APIPermission::kFileSystemDirectory)) {
811 error_ = kRequiresFileSystemDirectoryError; 729 return RespondNow(Error(kRequiresFileSystemDirectoryError));
812 return false;
813 } 730 }
814 if (multiple_) { 731 if (multiple_) {
815 error_ = kMultipleUnsupportedError; 732 return RespondNow(Error(kMultipleUnsupportedError));
816 return false;
817 } 733 }
818 picker_type = ui::SelectFileDialog::SELECT_FOLDER; 734 picker_type = ui::SelectFileDialog::SELECT_FOLDER;
819 } 735 }
820 736
821 base::FilePath::StringType suggested_extension; 737 base::FilePath::StringType suggested_extension;
822 BuildSuggestion(options->suggested_name.get(), &suggested_name, 738 BuildSuggestion(options->suggested_name.get(), &suggested_name,
823 &suggested_extension); 739 &suggested_extension);
824 740
825 BuildFileTypeInfo(&file_type_info, suggested_extension, 741 BuildFileTypeInfo(&file_type_info, suggested_extension,
826 options->accepts.get(), options->accepts_all_types.get()); 742 options->accepts.get(), options->accepts_all_types.get());
827 } 743 }
828 744
829 file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH; 745 file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
830 746
831 base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory( 747 base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory(
832 ExtensionPrefs::Get(GetProfile()), extension()->id()); 748 ExtensionPrefs::Get(browser_context()), extension()->id());
833 749
834 if (previous_path.empty()) { 750 if (previous_path.empty()) {
835 SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info, 751 SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info,
836 picker_type, false); 752 picker_type, false);
837 return true; 753 return RespondLater();
838 } 754 }
839 755
840 base::Callback<void(bool)> set_initial_path_callback = base::Bind( 756 base::Callback<void(bool)> set_initial_path_callback = base::Bind(
841 &FileSystemChooseEntryFunction::SetInitialPathAndShowPicker, this, 757 &FileSystemChooseEntryFunction::SetInitialPathAndShowPicker, this,
842 previous_path, suggested_name, file_type_info, picker_type); 758 previous_path, suggested_name, file_type_info, picker_type);
843 759
844 // Check whether the |previous_path| is a non-native directory. 760 // Check whether the |previous_path| is a non-native directory.
845 #if defined(OS_CHROMEOS) 761 #if defined(OS_CHROMEOS)
846 if (file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), 762 NonNativeFileSystemDelegate* delegate =
847 previous_path)) { 763 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
848 file_manager::util::IsNonNativeLocalPathDirectory( 764 if (delegate &&
849 GetProfile(), previous_path, set_initial_path_callback); 765 delegate->IsUnderNonNativeLocalPath(browser_context(), previous_path)) {
850 return true; 766 delegate->IsNonNativeLocalPathDirectory(browser_context(), previous_path,
767 set_initial_path_callback);
768 return RespondLater();
851 } 769 }
852 #endif 770 #endif
853 base::PostTaskWithTraitsAndReplyWithResult( 771 base::PostTaskWithTraitsAndReplyWithResult(
854 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 772 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
855 base::Bind(&base::DirectoryExists, previous_path), 773 base::Bind(&base::DirectoryExists, previous_path),
856 set_initial_path_callback); 774 set_initial_path_callback);
857 775
858 return true; 776 return RespondLater();
859 } 777 }
860 778
861 bool FileSystemRetainEntryFunction::RunAsync() { 779 ExtensionFunction::ResponseAction FileSystemRetainEntryFunction::Run() {
862 std::string entry_id; 780 std::string entry_id;
863 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 781 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
864 SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); 782
783 FileSystemDelegate* delegate =
784 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
785 DCHECK(delegate);
786
787 SavedFilesServiceInterface* saved_files_service =
788 delegate->GetSavedFilesService(browser_context());
789 DCHECK(saved_files_service);
790
865 // Add the file to the retain list if it is not already on there. 791 // Add the file to the retain list if it is not already on there.
866 if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) { 792 if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) {
867 std::string filesystem_name; 793 std::string filesystem_name;
868 std::string filesystem_path; 794 std::string filesystem_path;
869 base::FilePath path; 795 base::FilePath path;
870 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); 796 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name));
871 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); 797 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path));
798 std::string error;
872 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 799 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
873 filesystem_name, filesystem_path, 800 filesystem_name, filesystem_path,
874 render_frame_host()->GetProcess()->GetID(), &path, &error_)) { 801 render_frame_host()->GetProcess()->GetID(), &path, &error)) {
875 return false; 802 return RespondNow(Error(error));
876 } 803 }
877 804
878 std::string filesystem_id; 805 std::string filesystem_id;
879 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) 806 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id))
880 return false; 807 return RespondNow(Error(kRetainEntryError));
881 808
882 const GURL site = util::GetSiteForExtensionId(extension_id(), GetProfile()); 809 const GURL site =
810 util::GetSiteForExtensionId(extension_id(), browser_context());
883 storage::FileSystemContext* const context = 811 storage::FileSystemContext* const context =
884 content::BrowserContext::GetStoragePartitionForSite(GetProfile(), site) 812 content::BrowserContext::GetStoragePartitionForSite(browser_context(),
813 site)
885 ->GetFileSystemContext(); 814 ->GetFileSystemContext();
886 const storage::FileSystemURL url = context->CreateCrackedFileSystemURL( 815 const storage::FileSystemURL url = context->CreateCrackedFileSystemURL(
887 site, storage::kFileSystemTypeIsolated, 816 site, storage::kFileSystemTypeIsolated,
888 IsolatedContext::GetInstance() 817 storage::IsolatedContext::GetInstance()
889 ->CreateVirtualRootPath(filesystem_id) 818 ->CreateVirtualRootPath(filesystem_id)
890 .Append(base::FilePath::FromUTF8Unsafe(filesystem_path))); 819 .Append(base::FilePath::FromUTF8Unsafe(filesystem_path)));
891 820
892 content::BrowserThread::PostTask( 821 content::BrowserThread::PostTask(
893 content::BrowserThread::IO, FROM_HERE, 822 content::BrowserThread::IO, FROM_HERE,
894 base::BindOnce( 823 base::BindOnce(
895 base::IgnoreResult( 824 base::IgnoreResult(
896 &storage::FileSystemOperationRunner::GetMetadata), 825 &storage::FileSystemOperationRunner::GetMetadata),
897 context->operation_runner()->AsWeakPtr(), url, 826 context->operation_runner()->AsWeakPtr(), url,
898 storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY, 827 storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
899 base::Bind( 828 base::Bind(
900 &PassFileInfoToUIThread, 829 &PassFileInfoToUIThread,
901 base::Bind(&FileSystemRetainEntryFunction::RetainFileEntry, 830 base::Bind(&FileSystemRetainEntryFunction::RetainFileEntry,
902 this, entry_id, path)))); 831 this, entry_id, path))));
903 return true; 832 return RespondLater();
904 } 833 }
905 834
906 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); 835 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id);
907 SendResponse(true); 836 return RespondNow(NoArguments());
908 return true;
909 } 837 }
910 838
911 void FileSystemRetainEntryFunction::RetainFileEntry( 839 void FileSystemRetainEntryFunction::RetainFileEntry(
912 const std::string& entry_id, 840 const std::string& entry_id,
913 const base::FilePath& path, 841 const base::FilePath& path,
914 std::unique_ptr<base::File::Info> file_info) { 842 std::unique_ptr<base::File::Info> file_info) {
915 if (!file_info) { 843 if (!file_info) {
916 SendResponse(false); 844 Respond(Error(kRetainEntryError));
917 return; 845 return;
918 } 846 }
919 847
920 SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); 848 FileSystemDelegate* delegate =
849 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
850 DCHECK(delegate);
851
852 SavedFilesServiceInterface* saved_files_service =
853 delegate->GetSavedFilesService(browser_context());
854 DCHECK(saved_files_service);
921 saved_files_service->RegisterFileEntry(extension_->id(), entry_id, path, 855 saved_files_service->RegisterFileEntry(extension_->id(), entry_id, path,
922 file_info->is_directory); 856 file_info->is_directory);
923 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); 857 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id);
924 SendResponse(true); 858 Respond(NoArguments());
925 } 859 }
926 860
927 ExtensionFunction::ResponseAction FileSystemIsRestorableFunction::Run() { 861 ExtensionFunction::ResponseAction FileSystemIsRestorableFunction::Run() {
928 std::string entry_id; 862 std::string entry_id;
929 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 863 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
864
865 FileSystemDelegate* delegate =
866 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
867 DCHECK(delegate);
868
869 SavedFilesServiceInterface* saved_files_service =
870 delegate->GetSavedFilesService(browser_context());
871 DCHECK(saved_files_service);
872
930 return RespondNow(OneArgument(base::MakeUnique<base::Value>( 873 return RespondNow(OneArgument(base::MakeUnique<base::Value>(
931 SavedFilesService::Get(Profile::FromBrowserContext(browser_context())) 874 saved_files_service->IsRegistered(extension_->id(), entry_id))));
932 ->IsRegistered(extension_->id(), entry_id))));
933 } 875 }
934 876
935 bool FileSystemRestoreEntryFunction::RunAsync() { 877 ExtensionFunction::ResponseAction FileSystemRestoreEntryFunction::Run() {
936 std::string entry_id; 878 std::string entry_id;
937 bool needs_new_entry; 879 bool needs_new_entry;
938 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 880 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
939 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry)); 881 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry));
940 const SavedFileEntry* file_entry = 882 FileSystemDelegate* delegate =
941 SavedFilesService::Get(GetProfile()) 883 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
942 ->GetFileEntry(extension_->id(), entry_id); 884 DCHECK(delegate);
943 if (!file_entry) {
944 error_ = kUnknownIdError;
945 return false;
946 }
947 885
948 SavedFilesService::Get(GetProfile()) 886 SavedFilesServiceInterface* saved_files_service =
949 ->EnqueueFileEntry(extension_->id(), entry_id); 887 delegate->GetSavedFilesService(browser_context());
888 DCHECK(saved_files_service);
889 const SavedFileEntry* file =
890 saved_files_service->GetFileEntry(extension_->id(), entry_id);
891 if (!file)
892 return RespondNow(Error(kUnknownIdError));
893
894 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id);
950 895
951 // Only create a new file entry if the renderer requests one. 896 // Only create a new file entry if the renderer requests one.
952 // |needs_new_entry| will be false if the renderer already has an Entry for 897 // |needs_new_entry| will be false if the renderer already has an Entry for
953 // |entry_id|. 898 // |entry_id|.
954 if (needs_new_entry) { 899 if (needs_new_entry) {
955 is_directory_ = file_entry->is_directory; 900 is_directory_ = file->is_directory;
956 std::unique_ptr<base::DictionaryValue> result = CreateResult(); 901 std::unique_ptr<base::DictionaryValue> result = CreateResult();
957 AddEntryToResult(file_entry->path, file_entry->id, result.get()); 902 AddEntryToResult(file->path, file->id, result.get());
958 SetResult(std::move(result)); 903 return RespondNow(OneArgument(std::move(result)));
959 } 904 }
960 SendResponse(true); 905 return RespondNow(NoArguments());
961 return true;
962 } 906 }
963 907
964 ExtensionFunction::ResponseAction FileSystemObserveDirectoryFunction::Run() { 908 ExtensionFunction::ResponseAction FileSystemObserveDirectoryFunction::Run() {
965 NOTIMPLEMENTED(); 909 NOTIMPLEMENTED();
966 return RespondNow(Error(kUnknownIdError)); 910 return RespondNow(Error(kUnknownIdError));
967 } 911 }
968 912
969 ExtensionFunction::ResponseAction FileSystemUnobserveEntryFunction::Run() { 913 ExtensionFunction::ResponseAction FileSystemUnobserveEntryFunction::Run() {
970 NOTIMPLEMENTED(); 914 NOTIMPLEMENTED();
971 return RespondNow(Error(kUnknownIdError)); 915 return RespondNow(Error(kUnknownIdError));
972 } 916 }
973 917
974 ExtensionFunction::ResponseAction FileSystemGetObservedEntriesFunction::Run() { 918 ExtensionFunction::ResponseAction FileSystemGetObservedEntriesFunction::Run() {
975 NOTIMPLEMENTED(); 919 NOTIMPLEMENTED();
976 return RespondNow(Error(kUnknownIdError)); 920 return RespondNow(Error(kUnknownIdError));
977 } 921 }
978 922
979 #if !defined(OS_CHROMEOS) 923 #if !defined(OS_CHROMEOS)
980 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { 924 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
981 using api::file_system::RequestFileSystem::Params; 925 using file_system::RequestFileSystem::Params;
982 const std::unique_ptr<Params> params(Params::Create(*args_)); 926 const std::unique_ptr<Params> params(Params::Create(*args_));
983 EXTENSION_FUNCTION_VALIDATE(params); 927 EXTENSION_FUNCTION_VALIDATE(params);
984 928
985 NOTIMPLEMENTED(); 929 NOTIMPLEMENTED();
986 return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); 930 return RespondNow(Error(kNotSupportedOnCurrentPlatformError));
987 } 931 }
988 932
989 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { 933 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() {
990 NOTIMPLEMENTED(); 934 NOTIMPLEMENTED();
991 return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); 935 return RespondNow(Error(kNotSupportedOnCurrentPlatformError));
992 } 936 }
993 #else 937 #else
994 938
995 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() 939 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() {}
996 : chrome_details_(this) {}
997 940
998 FileSystemRequestFileSystemFunction::~FileSystemRequestFileSystemFunction() {} 941 FileSystemRequestFileSystemFunction::~FileSystemRequestFileSystemFunction() {}
999 942
1000 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { 943 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
1001 using api::file_system::RequestFileSystem::Params; 944 using file_system::RequestFileSystem::Params;
1002 const std::unique_ptr<Params> params(Params::Create(*args_)); 945 const std::unique_ptr<Params> params(Params::Create(*args_));
1003 EXTENSION_FUNCTION_VALIDATE(params); 946 EXTENSION_FUNCTION_VALIDATE(params);
1004 947
948 FileSystemDelegate* delegate =
949 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
950 DCHECK(delegate);
1005 // Only kiosk apps in kiosk sessions can use this API. 951 // Only kiosk apps in kiosk sessions can use this API.
1006 // Additionally it is enabled for whitelisted component extensions and apps. 952 // Additionally it is enabled for whitelisted component extensions and apps.
1007 file_system_api::ConsentProviderDelegate consent_provider_delegate( 953 if (!delegate->IsGrantable(browser_context(), render_frame_host(),
1008 chrome_details_.GetProfile(), render_frame_host()); 954 *extension())) {
1009 file_system_api::ConsentProvider consent_provider(&consent_provider_delegate);
1010
1011 if (!consent_provider.IsGrantable(*extension()))
1012 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 955 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
1013
1014 using file_manager::VolumeManager;
1015 using file_manager::Volume;
1016 VolumeManager* const volume_manager =
1017 VolumeManager::Get(chrome_details_.GetProfile());
1018 DCHECK(volume_manager);
1019
1020 const bool writable =
1021 params->options.writable.get() && *params->options.writable.get();
1022 if (writable &&
1023 !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
1024 return RespondNow(Error(kRequiresFileSystemWriteError));
1025 } 956 }
1026 957
1027 base::WeakPtr<file_manager::Volume> volume = 958 delegate->RequestFileSystem(
1028 volume_manager->FindVolumeById(params->options.volume_id); 959 browser_context(), this, *extension(), params->options.volume_id,
1029 if (!volume.get()) 960 params->options.writable.get() && *params->options.writable.get(),
1030 return RespondNow(Error(kVolumeNotFoundError)); 961 base::Bind(&FileSystemRequestFileSystemFunction::OnGotFileSystem, this),
962 base::Bind(&FileSystemRequestFileSystemFunction::OnError, this));
1031 963
1032 const GURL site = 964 return did_respond() ? AlreadyResponded() : RespondLater();
1033 util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile());
1034 scoped_refptr<storage::FileSystemContext> file_system_context =
1035 content::BrowserContext::GetStoragePartitionForSite(
1036 chrome_details_.GetProfile(), site)
1037 ->GetFileSystemContext();
1038 storage::ExternalFileSystemBackend* const backend =
1039 file_system_context->external_backend();
1040 DCHECK(backend);
1041
1042 base::FilePath virtual_path;
1043 if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path))
1044 return RespondNow(Error(kSecurityError));
1045
1046 if (writable && (volume->is_read_only()))
1047 return RespondNow(Error(kSecurityError));
1048
1049 consent_provider.RequestConsent(
1050 *extension(), volume, writable,
1051 base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived, this,
1052 volume, writable));
1053 return RespondLater();
1054 } 965 }
1055 966
1056 void FileSystemRequestFileSystemFunction::OnConsentReceived( 967 void FileSystemRequestFileSystemFunction::OnGotFileSystem(
1057 const base::WeakPtr<file_manager::Volume>& volume, 968 const std::string& id,
1058 bool writable, 969 const std::string& path) {
1059 ConsentProvider::Consent result) {
1060 using file_manager::VolumeManager;
1061 using file_manager::Volume;
1062
1063 // Render frame host can be gone before this callback method is executed.
1064 if (!render_frame_host()) {
1065 Respond(Error(""));
1066 return;
1067 }
1068
1069 switch (result) {
1070 case ConsentProvider::CONSENT_REJECTED:
1071 Respond(Error(kSecurityError));
1072 return;
1073
1074 case ConsentProvider::CONSENT_IMPOSSIBLE:
1075 Respond(Error(kConsentImpossible));
1076 return;
1077
1078 case ConsentProvider::CONSENT_GRANTED:
1079 break;
1080 }
1081
1082 if (!volume.get()) {
1083 Respond(Error(kVolumeNotFoundError));
1084 return;
1085 }
1086
1087 const GURL site =
1088 util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile());
1089 scoped_refptr<storage::FileSystemContext> file_system_context =
1090 content::BrowserContext::GetStoragePartitionForSite(
1091 chrome_details_.GetProfile(), site)
1092 ->GetFileSystemContext();
1093 storage::ExternalFileSystemBackend* const backend =
1094 file_system_context->external_backend();
1095 DCHECK(backend);
1096
1097 base::FilePath virtual_path;
1098 if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path)) {
1099 Respond(Error(kSecurityError));
1100 return;
1101 }
1102
1103 storage::IsolatedContext* const isolated_context =
1104 storage::IsolatedContext::GetInstance();
1105 DCHECK(isolated_context);
1106
1107 const storage::FileSystemURL original_url =
1108 file_system_context->CreateCrackedFileSystemURL(
1109 GURL(std::string(kExtensionScheme) + url::kStandardSchemeSeparator +
1110 extension_id()),
1111 storage::kFileSystemTypeExternal, virtual_path);
1112
1113 // Set a fixed register name, as the automatic one would leak the mount point
1114 // directory.
1115 std::string register_name = "fs";
1116 const std::string file_system_id =
1117 isolated_context->RegisterFileSystemForPath(
1118 storage::kFileSystemTypeNativeForPlatformApp,
1119 std::string() /* file_system_id */, original_url.path(),
1120 &register_name);
1121 if (file_system_id.empty()) {
1122 Respond(Error(kSecurityError));
1123 return;
1124 }
1125
1126 backend->GrantFileAccessToExtension(extension_->id(), virtual_path);
1127
1128 // Grant file permissions to the renderer hosting component.
1129 content::ChildProcessSecurityPolicy* policy =
1130 content::ChildProcessSecurityPolicy::GetInstance();
1131 DCHECK(policy);
1132
1133 // Read-only permisisons.
1134 policy->GrantReadFile(render_frame_host()->GetProcess()->GetID(),
1135 volume->mount_path());
1136 policy->GrantReadFileSystem(render_frame_host()->GetProcess()->GetID(),
1137 file_system_id);
1138
1139 // Additional write permissions.
1140 if (writable) {
1141 policy->GrantCreateReadWriteFile(render_frame_host()->GetProcess()->GetID(),
1142 volume->mount_path());
1143 policy->GrantCopyInto(render_frame_host()->GetProcess()->GetID(),
1144 volume->mount_path());
1145 policy->GrantWriteFileSystem(render_frame_host()->GetProcess()->GetID(),
1146 file_system_id);
1147 policy->GrantDeleteFromFileSystem(
1148 render_frame_host()->GetProcess()->GetID(), file_system_id);
1149 policy->GrantCreateFileForFileSystem(
1150 render_frame_host()->GetProcess()->GetID(), file_system_id);
1151 }
1152
1153 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 970 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
1154 dict->SetString("file_system_id", file_system_id); 971 dict->SetString("file_system_id", id);
1155 dict->SetString("file_system_path", register_name); 972 dict->SetString("file_system_path", path);
1156
1157 Respond(OneArgument(std::move(dict))); 973 Respond(OneArgument(std::move(dict)));
1158 } 974 }
1159 975
1160 FileSystemGetVolumeListFunction::FileSystemGetVolumeListFunction() 976 void FileSystemRequestFileSystemFunction::OnError(const std::string& error) {
1161 : chrome_details_(this) {} 977 Respond(Error(error));
978 }
979
980 FileSystemGetVolumeListFunction::FileSystemGetVolumeListFunction() {}
1162 981
1163 FileSystemGetVolumeListFunction::~FileSystemGetVolumeListFunction() {} 982 FileSystemGetVolumeListFunction::~FileSystemGetVolumeListFunction() {}
1164 983
1165 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { 984 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() {
985 FileSystemDelegate* delegate =
986 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
987 DCHECK(delegate);
1166 // Only kiosk apps in kiosk sessions can use this API. 988 // Only kiosk apps in kiosk sessions can use this API.
1167 // Additionally it is enabled for whitelisted component extensions and apps. 989 // Additionally it is enabled for whitelisted component extensions and apps.
1168 file_system_api::ConsentProviderDelegate consent_provider_delegate( 990 if (!delegate->IsGrantable(browser_context(), render_frame_host(),
1169 chrome_details_.GetProfile(), render_frame_host()); 991 *extension())) {
1170 file_system_api::ConsentProvider consent_provider(&consent_provider_delegate); 992 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
993 }
1171 994
1172 if (!consent_provider.IsGrantable(*extension())) 995 delegate->GetVolumeList(
1173 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 996 browser_context(),
1174 std::vector<api::file_system::Volume> result_volume_list; 997 base::Bind(&FileSystemGetVolumeListFunction::OnGotVolumeList, this),
1175 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list); 998 base::Bind(&FileSystemGetVolumeListFunction::OnError, this));
1176 999
1177 return RespondNow(ArgumentList( 1000 return did_respond() ? AlreadyResponded() : RespondLater();
1178 api::file_system::GetVolumeList::Results::Create(result_volume_list))); 1001 }
1002
1003 void FileSystemGetVolumeListFunction::OnGotVolumeList(
1004 const std::vector<file_system::Volume>& volumes) {
1005 Respond(ArgumentList(file_system::GetVolumeList::Results::Create(volumes)));
1006 }
1007
1008 void FileSystemGetVolumeListFunction::OnError(const std::string& error) {
1009 Respond(Error(error));
1179 } 1010 }
1180 #endif 1011 #endif
1181 1012
1182 } // namespace extensions 1013 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/file_system/file_system_api.h ('k') | extensions/browser/api/file_system/file_system_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698