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

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

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