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