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