| 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 "chrome/browser/extensions/api/file_system/file_system_api.h" | 
| 6 | 6 | 
| 7 #include <set> | 7 #include <set> | 
| 8 | 8 | 
| 9 #include "apps/saved_files_service.h" | 9 #include "apps/saved_files_service.h" | 
| 10 #include "base/bind.h" | 10 #include "base/bind.h" | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 51 #include "ui/base/l10n/l10n_util.h" | 51 #include "ui/base/l10n/l10n_util.h" | 
| 52 #include "ui/shell_dialogs/select_file_dialog.h" | 52 #include "ui/shell_dialogs/select_file_dialog.h" | 
| 53 #include "ui/shell_dialogs/selected_file_info.h" | 53 #include "ui/shell_dialogs/selected_file_info.h" | 
| 54 | 54 | 
| 55 #if defined(OS_MACOSX) | 55 #if defined(OS_MACOSX) | 
| 56 #include <CoreFoundation/CoreFoundation.h> | 56 #include <CoreFoundation/CoreFoundation.h> | 
| 57 #include "base/mac/foundation_util.h" | 57 #include "base/mac/foundation_util.h" | 
| 58 #endif | 58 #endif | 
| 59 | 59 | 
| 60 #if defined(OS_CHROMEOS) | 60 #if defined(OS_CHROMEOS) | 
|  | 61 #include "base/thread_task_runner_handle.h" | 
|  | 62 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" | 
| 61 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" | 63 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" | 
|  | 64 #include "chrome/browser/chromeos/file_manager/volume_manager.h" | 
|  | 65 #include "components/user_manager/user_manager.h" | 
|  | 66 #include "extensions/common/manifest_handlers/kiosk_mode_info.h" | 
| 62 #endif | 67 #endif | 
| 63 | 68 | 
| 64 using apps::SavedFileEntry; | 69 using apps::SavedFileEntry; | 
| 65 using apps::SavedFilesService; | 70 using apps::SavedFilesService; | 
| 66 using storage::IsolatedContext; | 71 using storage::IsolatedContext; | 
| 67 | 72 | 
| 68 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " | 73 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " | 
| 69     "be called from a background page."; | 74     "be called from a background page."; | 
| 70 const char kUserCancelled[] = "User cancelled"; | 75 const char kUserCancelled[] = "User cancelled"; | 
| 71 const char kWritableFileErrorFormat[] = "Error opening %s"; | 76 const char kWritableFileErrorFormat[] = "Error opening %s"; | 
| 72 const char kRequiresFileSystemWriteError[] = | 77 const char kRequiresFileSystemWriteError[] = | 
| 73     "Operation requires fileSystem.write permission"; | 78     "Operation requires fileSystem.write permission"; | 
| 74 const char kRequiresFileSystemDirectoryError[] = | 79 const char kRequiresFileSystemDirectoryError[] = | 
| 75     "Operation requires fileSystem.directory permission"; | 80     "Operation requires fileSystem.directory permission"; | 
| 76 const char kMultipleUnsupportedError[] = | 81 const char kMultipleUnsupportedError[] = | 
| 77     "acceptsMultiple: true is not supported for 'saveFile'"; | 82     "acceptsMultiple: true is not supported for 'saveFile'"; | 
| 78 const char kUnknownIdError[] = "Unknown id"; | 83 const char kUnknownIdError[] = "Unknown id"; | 
|  | 84 const char kNotSupportedError[] = "Operation not supported."; | 
|  | 85 | 
|  | 86 #if defined(OS_CHROMEOS) | 
|  | 87 const char kVolumeNotFoundError[] = "Volume not found."; | 
|  | 88 const char kSecurityError[] = "Security error."; | 
|  | 89 #endif | 
| 79 | 90 | 
| 80 namespace file_system = extensions::api::file_system; | 91 namespace file_system = extensions::api::file_system; | 
| 81 namespace ChooseEntry = file_system::ChooseEntry; | 92 namespace ChooseEntry = file_system::ChooseEntry; | 
| 82 | 93 | 
| 83 namespace { | 94 namespace { | 
| 84 | 95 | 
| 85 bool g_skip_picker_for_test = false; | 96 bool g_skip_picker_for_test = false; | 
| 86 bool g_use_suggested_path_for_test = false; | 97 bool g_use_suggested_path_for_test = false; | 
| 87 base::FilePath* g_path_to_be_picked_for_test; | 98 base::FilePath* g_path_to_be_picked_for_test; | 
| 88 std::vector<base::FilePath>* g_paths_to_be_picked_for_test; | 99 std::vector<base::FilePath>* g_paths_to_be_picked_for_test; | 
| (...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 987   error_ = kUnknownIdError; | 998   error_ = kUnknownIdError; | 
| 988   return false; | 999   return false; | 
| 989 } | 1000 } | 
| 990 | 1001 | 
| 991 bool FileSystemGetObservedEntriesFunction::RunSync() { | 1002 bool FileSystemGetObservedEntriesFunction::RunSync() { | 
| 992   NOTIMPLEMENTED(); | 1003   NOTIMPLEMENTED(); | 
| 993   error_ = kUnknownIdError; | 1004   error_ = kUnknownIdError; | 
| 994   return false; | 1005   return false; | 
| 995 } | 1006 } | 
| 996 | 1007 | 
|  | 1008 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() | 
|  | 1009     : chrome_details_(this) { | 
|  | 1010 } | 
|  | 1011 | 
|  | 1012 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { | 
|  | 1013   using extensions::api::file_system::RequestFileSystem::Params; | 
|  | 1014   const scoped_ptr<Params> params(Params::Create(*args_)); | 
|  | 1015   EXTENSION_FUNCTION_VALIDATE(params); | 
|  | 1016 | 
|  | 1017 #if !defined(OS_CHROMEOS) | 
|  | 1018   NOTIMPLEMENTED(); | 
|  | 1019   return RespondNow(Error(kNotSupportedError)); | 
|  | 1020 | 
|  | 1021 #else | 
|  | 1022   using file_manager::VolumeManager; | 
|  | 1023   using file_manager::VolumeInfo; | 
|  | 1024   VolumeManager* const volume_manager = | 
|  | 1025       VolumeManager::Get(chrome_details_.GetProfile()); | 
|  | 1026   DCHECK(volume_manager); | 
|  | 1027 | 
|  | 1028   const bool writable = | 
|  | 1029       params->options.writable.get() && *params->options.writable.get(); | 
|  | 1030 | 
|  | 1031   // Only kiosk apps in kiosk sessions can use this API. Additionally component | 
|  | 1032   // extensions and apps, which is not documented though. | 
|  | 1033   if ((!user_manager::UserManager::Get()->IsLoggedInAsKioskApp() || | 
|  | 1034        !KioskModeInfo::IsKioskEnabled(extension())) && | 
|  | 1035       extension()->location() != Manifest::COMPONENT) { | 
|  | 1036     return RespondNow(Error(kNotSupportedError)); | 
|  | 1037   } | 
|  | 1038 | 
|  | 1039   if (writable && | 
|  | 1040       !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { | 
|  | 1041     return RespondNow(Error(kRequiresFileSystemWriteError)); | 
|  | 1042   } | 
|  | 1043 | 
|  | 1044   VolumeInfo volume_info; | 
|  | 1045   if (!volume_manager->FindVolumeInfoById(params->options.volume_id, | 
|  | 1046                                           &volume_info)) { | 
|  | 1047     return RespondNow(Error(kVolumeNotFoundError)); | 
|  | 1048   } | 
|  | 1049 | 
|  | 1050   const GURL site = extensions::util::GetSiteForExtensionId( | 
|  | 1051       extension_id(), chrome_details_.GetProfile()); | 
|  | 1052   scoped_refptr<storage::FileSystemContext> file_system_context = | 
|  | 1053       content::BrowserContext::GetStoragePartitionForSite( | 
|  | 1054           chrome_details_.GetProfile(), site)->GetFileSystemContext(); | 
|  | 1055   storage::ExternalFileSystemBackend* const backend = | 
|  | 1056       file_system_context->external_backend(); | 
|  | 1057   DCHECK(backend); | 
|  | 1058 | 
|  | 1059   base::FilePath virtual_path; | 
|  | 1060   if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path)) | 
|  | 1061     return RespondNow(Error(kSecurityError)); | 
|  | 1062 | 
|  | 1063   if (writable && (volume_info.is_read_only)) | 
|  | 1064     return RespondNow(Error(kSecurityError)); | 
|  | 1065 | 
|  | 1066   const bool requires_consent = | 
|  | 1067       !chromeos::KioskAppManager::Get()->IsAutoLaunchEnabled() && | 
|  | 1068       extension()->location() != Manifest::COMPONENT; | 
|  | 1069   if (!requires_consent) { | 
|  | 1070     // Grant the permission without showing the dialog. | 
|  | 1071     base::ThreadTaskRunnerHandle::Get()->PostTask( | 
|  | 1072         FROM_HERE, | 
|  | 1073         base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived, | 
|  | 1074                    this, volume_info.volume_id, writable, true /* granted */)); | 
|  | 1075   } else { | 
|  | 1076     // TODO(mtomasz): Create a better display name, which is the most meaningful | 
|  | 1077     // to the user. | 
|  | 1078     const std::string display_name = !volume_info.volume_label.empty() | 
|  | 1079                                          ? volume_info.volume_label | 
|  | 1080                                          : volume_info.volume_id; | 
|  | 1081     RequestConsent( | 
|  | 1082         display_name, writable, | 
|  | 1083         base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived, | 
|  | 1084                    this, volume_info.volume_id, writable)); | 
|  | 1085   } | 
|  | 1086 | 
|  | 1087   return RespondLater(); | 
|  | 1088 #endif | 
|  | 1089 } | 
|  | 1090 | 
|  | 1091 #if defined(OS_CHROMEOS) | 
|  | 1092 void FileSystemRequestFileSystemFunction::RequestConsent( | 
|  | 1093     const std::string& display_name, | 
|  | 1094     bool writable, | 
|  | 1095     const base::Callback<void(bool)>& callback) { | 
|  | 1096   // TODO(mtomasz): Implement the consent dialog. | 
|  | 1097   callback.Run(false); | 
|  | 1098 } | 
|  | 1099 | 
|  | 1100 void FileSystemRequestFileSystemFunction::OnConsentReceived( | 
|  | 1101     const std::string& volume_id, | 
|  | 1102     bool writable, | 
|  | 1103     bool granted) { | 
|  | 1104   using file_manager::VolumeManager; | 
|  | 1105   using file_manager::VolumeInfo; | 
|  | 1106 | 
|  | 1107   if (!granted) { | 
|  | 1108     SetError(kSecurityError); | 
|  | 1109     SendResponse(false); | 
|  | 1110     return; | 
|  | 1111   } | 
|  | 1112 | 
|  | 1113   // Fetch the volume again, in case it's gone by the time the permission is | 
|  | 1114   // granted. | 
|  | 1115   VolumeManager* const volume_manager = | 
|  | 1116       VolumeManager::Get(chrome_details_.GetProfile()); | 
|  | 1117   DCHECK(volume_manager); | 
|  | 1118 | 
|  | 1119   VolumeInfo volume_info; | 
|  | 1120   if (!volume_manager->FindVolumeInfoById(volume_id, &volume_info)) { | 
|  | 1121     SetError(kVolumeNotFoundError); | 
|  | 1122     SendResponse(false); | 
|  | 1123     return; | 
|  | 1124   } | 
|  | 1125 | 
|  | 1126   const GURL site = extensions::util::GetSiteForExtensionId( | 
|  | 1127       extension_id(), chrome_details_.GetProfile()); | 
|  | 1128   scoped_refptr<storage::FileSystemContext> file_system_context = | 
|  | 1129       content::BrowserContext::GetStoragePartitionForSite( | 
|  | 1130           chrome_details_.GetProfile(), site)->GetFileSystemContext(); | 
|  | 1131   storage::ExternalFileSystemBackend* const backend = | 
|  | 1132       file_system_context->external_backend(); | 
|  | 1133   DCHECK(backend); | 
|  | 1134 | 
|  | 1135   // The volume may be unmounted and remounted by the time we reach this logic. | 
|  | 1136   // TODO(mtomasz): Add a unique identifier to VolumeInfo to guarantee that the | 
|  | 1137   // permissions are granted to exactly that volume which was plugged in when | 
|  | 1138   // the dialog was shown. | 
|  | 1139   base::FilePath virtual_path; | 
|  | 1140   if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path)) { | 
|  | 1141     SetError(kSecurityError); | 
|  | 1142     SendResponse(false); | 
|  | 1143     return; | 
|  | 1144   } | 
|  | 1145 | 
|  | 1146   storage::IsolatedContext* const isolated_context = | 
|  | 1147       storage::IsolatedContext::GetInstance(); | 
|  | 1148   DCHECK(isolated_context); | 
|  | 1149 | 
|  | 1150   const storage::FileSystemURL original_url = | 
|  | 1151       file_system_context->CreateCrackedFileSystemURL( | 
|  | 1152           GURL("chrome-extension://" + extension_id()), | 
|  | 1153           storage::kFileSystemTypeExternal, virtual_path); | 
|  | 1154 | 
|  | 1155   // Set a fixed register name, as the automatic one would leak the mount point | 
|  | 1156   // directory. | 
|  | 1157   std::string register_name = "fs"; | 
|  | 1158   const std::string file_system_id = | 
|  | 1159       isolated_context->RegisterFileSystemForPath( | 
|  | 1160           storage::kFileSystemTypeNativeForPlatformApp, | 
|  | 1161           std::string() /* file_system_id */, original_url.path(), | 
|  | 1162           ®ister_name); | 
|  | 1163   if (file_system_id.empty()) { | 
|  | 1164     SetError(kSecurityError); | 
|  | 1165     SendResponse(false); | 
|  | 1166     return; | 
|  | 1167   } | 
|  | 1168 | 
|  | 1169   backend->GrantFileAccessToExtension(extension_->id(), virtual_path); | 
|  | 1170 | 
|  | 1171   // Grant file permissions to the renderer hosting component. | 
|  | 1172   content::ChildProcessSecurityPolicy* policy = | 
|  | 1173       content::ChildProcessSecurityPolicy::GetInstance(); | 
|  | 1174   DCHECK(policy); | 
|  | 1175 | 
|  | 1176   // Read-only permisisons. | 
|  | 1177   policy->GrantReadFile(render_view_host()->GetProcess()->GetID(), | 
|  | 1178                         volume_info.mount_path); | 
|  | 1179   policy->GrantReadFileSystem(render_view_host()->GetProcess()->GetID(), | 
|  | 1180                               file_system_id); | 
|  | 1181 | 
|  | 1182   // Additional write permissions. | 
|  | 1183   if (writable) { | 
|  | 1184     policy->GrantCreateReadWriteFile(render_view_host()->GetProcess()->GetID(), | 
|  | 1185                                      volume_info.mount_path); | 
|  | 1186     policy->GrantCopyInto(render_view_host()->GetProcess()->GetID(), | 
|  | 1187                           volume_info.mount_path); | 
|  | 1188     policy->GrantWriteFileSystem(render_view_host()->GetProcess()->GetID(), | 
|  | 1189                                  file_system_id); | 
|  | 1190     policy->GrantDeleteFromFileSystem(render_view_host()->GetProcess()->GetID(), | 
|  | 1191                                       file_system_id); | 
|  | 1192     policy->GrantCreateFileForFileSystem( | 
|  | 1193         render_view_host()->GetProcess()->GetID(), file_system_id); | 
|  | 1194   } | 
|  | 1195 | 
|  | 1196   base::DictionaryValue* const dict = new base::DictionaryValue(); | 
|  | 1197   dict->SetString("file_system_id", file_system_id); | 
|  | 1198   dict->SetString("file_system_path", register_name); | 
|  | 1199 | 
|  | 1200   SetResult(dict); | 
|  | 1201   SendResponse(true); | 
|  | 1202 } | 
|  | 1203 #endif | 
|  | 1204 | 
| 997 }  // namespace extensions | 1205 }  // namespace extensions | 
| OLD | NEW | 
|---|