| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/chromeos/file_system_provider/service.h" | 5 #include "chrome/browser/chromeos/file_system_provider/service.h" |
| 6 | 6 |
| 7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
| 8 #include "base/prefs/pref_service.h" | 8 #include "base/prefs/pref_service.h" |
| 9 #include "base/prefs/scoped_user_pref_update.h" | 9 #include "base/prefs/scoped_user_pref_update.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "storage/common/fileapi/file_system_mount_option.h" | 26 #include "storage/common/fileapi/file_system_mount_option.h" |
| 27 | 27 |
| 28 namespace chromeos { | 28 namespace chromeos { |
| 29 namespace file_system_provider { | 29 namespace file_system_provider { |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 // Maximum number of file systems to be mounted in the same time, per profile. | 32 // Maximum number of file systems to be mounted in the same time, per profile. |
| 33 const size_t kMaxFileSystems = 16; | 33 const size_t kMaxFileSystems = 16; |
| 34 | 34 |
| 35 // Default factory for provided file systems. |profile| must not be NULL. | 35 // Default factory for provided file systems. |profile| must not be NULL. |
| 36 template <int source = Source_Type::extension> |
| 36 ProvidedFileSystemInterface* CreateProvidedFileSystem( | 37 ProvidedFileSystemInterface* CreateProvidedFileSystem( |
| 37 Profile* profile, | 38 Profile* profile, |
| 38 const ProvidedFileSystemInfo& file_system_info) { | 39 const ProvidedFileSystemInfo& file_system_info) { |
| 39 DCHECK(profile); | 40 DCHECK(profile); |
| 40 return new ThrottledFileSystem( | 41 return new ThrottledFileSystem(make_scoped_ptr( |
| 41 make_scoped_ptr(new ProvidedFileSystem(profile, file_system_info))); | 42 new ProvidedFileSystem<source>(profile, file_system_info))); |
| 42 } | 43 } |
| 43 | 44 |
| 44 } // namespace | 45 } // namespace |
| 45 | 46 |
| 46 ProvidingExtensionInfo::ProvidingExtensionInfo() | 47 ProvidingExtensionInfo::ProvidingExtensionInfo() |
| 47 : can_configure(false), can_add(false) { | 48 : can_configure(false), can_add(false) { |
| 48 } | 49 } |
| 49 | 50 |
| 50 ProvidingExtensionInfo::~ProvidingExtensionInfo() { | 51 ProvidingExtensionInfo::~ProvidingExtensionInfo() { |
| 51 } | 52 } |
| 52 | 53 |
| 53 Service::Service(Profile* profile, | 54 Service::Service(Profile* profile, |
| 54 extensions::ExtensionRegistry* extension_registry) | 55 extensions::ExtensionRegistry* extension_registry) |
| 55 : profile_(profile), | 56 : profile_(profile), |
| 56 extension_registry_(extension_registry), | 57 extension_registry_(extension_registry), |
| 57 file_system_factory_(base::Bind(&CreateProvidedFileSystem)), | 58 file_system_factory_( |
| 59 base::Bind(&CreateProvidedFileSystem<Source_Type::extension>)), |
| 58 registry_(new Registry(profile)), | 60 registry_(new Registry(profile)), |
| 59 weak_ptr_factory_(this) { | 61 weak_ptr_factory_(this) { |
| 60 extension_registry_->AddObserver(this); | 62 extension_registry_->AddObserver(this); |
| 61 } | 63 } |
| 62 | 64 |
| 63 Service::~Service() { | 65 Service::~Service() { |
| 64 extension_registry_->RemoveObserver(this); | 66 extension_registry_->RemoveObserver(this); |
| 65 | 67 |
| 66 // Provided file systems should be already unmounted because of receiving | 68 // Provided file systems should be already unmounted because of receiving |
| 67 // OnExtensionUnload calls for each installed extension. However, for tests | 69 // OnExtensionUnload calls for each installed extension. However, for tests |
| 68 // we may still have mounted extensions. | 70 // we may still have mounted extensions. |
| 69 // TODO(mtomasz): Create a TestingService class and remove this code. | 71 // TODO(mtomasz): Create a TestingService class and remove this code. |
| 70 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); | 72 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); |
| 71 while (it != file_system_map_.end()) { | 73 while (it != file_system_map_.end()) { |
| 72 const std::string file_system_id = | 74 const std::string file_system_id = |
| 73 it->second->GetFileSystemInfo().file_system_id(); | 75 it->second->GetFileSystemInfo().file_system_id(); |
| 74 const std::string extension_id = | 76 const std::string source_id = |
| 75 it->second->GetFileSystemInfo().extension_id(); | 77 it->second->GetFileSystemInfo().source_id(); |
| 76 ++it; | 78 ++it; |
| 77 const base::File::Error unmount_result = UnmountFileSystem( | 79 const base::File::Error unmount_result = UnmountFileSystem( |
| 78 extension_id, file_system_id, UNMOUNT_REASON_SHUTDOWN); | 80 source_id, file_system_id, UNMOUNT_REASON_SHUTDOWN); |
| 79 DCHECK_EQ(base::File::FILE_OK, unmount_result); | 81 DCHECK_EQ(base::File::FILE_OK, unmount_result); |
| 80 } | 82 } |
| 81 | 83 |
| 82 DCHECK_EQ(0u, file_system_map_.size()); | 84 DCHECK_EQ(0u, file_system_map_.size()); |
| 83 STLDeleteValues(&file_system_map_); | 85 STLDeleteValues(&file_system_map_); |
| 84 } | 86 } |
| 85 | 87 |
| 86 // static | 88 // static |
| 87 Service* Service::Get(content::BrowserContext* context) { | 89 Service* Service::Get(content::BrowserContext* context) { |
| 88 return ServiceFactory::Get(context); | 90 return ServiceFactory::Get(context); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 102 const FileSystemFactoryCallback& factory_callback) { | 104 const FileSystemFactoryCallback& factory_callback) { |
| 103 DCHECK(!factory_callback.is_null()); | 105 DCHECK(!factory_callback.is_null()); |
| 104 file_system_factory_ = factory_callback; | 106 file_system_factory_ = factory_callback; |
| 105 } | 107 } |
| 106 | 108 |
| 107 void Service::SetRegistryForTesting(scoped_ptr<RegistryInterface> registry) { | 109 void Service::SetRegistryForTesting(scoped_ptr<RegistryInterface> registry) { |
| 108 DCHECK(registry); | 110 DCHECK(registry); |
| 109 registry_.reset(registry.release()); | 111 registry_.reset(registry.release()); |
| 110 } | 112 } |
| 111 | 113 |
| 112 base::File::Error Service::MountFileSystem(const std::string& extension_id, | 114 base::File::Error Service::MountFileSystem(const std::string& source_id, |
| 113 const MountOptions& options) { | 115 const MountOptions& options, |
| 114 return MountFileSystemInternal(extension_id, options, MOUNT_CONTEXT_USER); | 116 Source_Type source_type) { |
| 117 switch (source_type) { |
| 118 case Source_Type::extension: |
| 119 case Source_Type::plugin: |
| 120 return MountFileSystemInternal(source_id, options, MOUNT_CONTEXT_USER, |
| 121 source_type); |
| 122 default: |
| 123 return base::File::Error::FILE_ERROR_INVALID_OPERATION; |
| 124 } |
| 115 } | 125 } |
| 116 | 126 |
| 117 base::File::Error Service::MountFileSystemInternal( | 127 base::File::Error Service::MountFileSystemInternal(const std::string& source_id, |
| 118 const std::string& extension_id, | 128 const MountOptions& options, |
| 119 const MountOptions& options, | 129 MountContext context, |
| 120 MountContext context) { | 130 Source_Type source_type) { |
| 121 DCHECK(thread_checker_.CalledOnValidThread()); | 131 DCHECK(thread_checker_.CalledOnValidThread()); |
| 122 | 132 |
| 123 // If already exists a file system provided by the same extension with this | 133 // If already exists a file system provided by the same source with this |
| 124 // id, then abort. | 134 // id, then abort. |
| 125 if (GetProvidedFileSystem(extension_id, options.file_system_id)) { | 135 if (GetProvidedFileSystem(source_id, options.file_system_id)) { |
| 126 FOR_EACH_OBSERVER( | 136 FOR_EACH_OBSERVER( |
| 127 Observer, observers_, | 137 Observer, observers_, |
| 128 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, | 138 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, |
| 129 base::File::FILE_ERROR_EXISTS)); | 139 base::File::FILE_ERROR_EXISTS)); |
| 130 return base::File::FILE_ERROR_EXISTS; | 140 return base::File::FILE_ERROR_EXISTS; |
| 131 } | 141 } |
| 132 | 142 |
| 133 // Restrict number of file systems to prevent system abusing. | 143 // Restrict number of file systems to prevent system abusing. |
| 134 if (file_system_map_.size() + 1 > kMaxFileSystems) { | 144 if (file_system_map_.size() + 1 > kMaxFileSystems) { |
| 135 FOR_EACH_OBSERVER( | 145 FOR_EACH_OBSERVER( |
| 136 Observer, observers_, | 146 Observer, observers_, |
| 137 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, | 147 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, |
| 138 base::File::FILE_ERROR_TOO_MANY_OPENED)); | 148 base::File::FILE_ERROR_TOO_MANY_OPENED)); |
| 139 return base::File::FILE_ERROR_TOO_MANY_OPENED; | 149 return base::File::FILE_ERROR_TOO_MANY_OPENED; |
| 140 } | 150 } |
| 141 | 151 |
| 142 storage::ExternalMountPoints* const mount_points = | 152 storage::ExternalMountPoints* const mount_points = |
| 143 storage::ExternalMountPoints::GetSystemInstance(); | 153 storage::ExternalMountPoints::GetSystemInstance(); |
| 144 DCHECK(mount_points); | 154 DCHECK(mount_points); |
| 145 | 155 |
| 146 // The mount point path and name are unique per system, since they are system | 156 // The mount point path and name are unique per system, since they are system |
| 147 // wide. This is necessary for copying between profiles. | 157 // wide. This is necessary for copying between profiles. |
| 148 const base::FilePath& mount_path = | 158 const base::FilePath& mount_path = |
| 149 util::GetMountPath(profile_, extension_id, options.file_system_id); | 159 util::GetMountPath(profile_, source_id, options.file_system_id); |
| 150 const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe(); | 160 const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe(); |
| 151 | 161 |
| 152 if (!mount_points->RegisterFileSystem( | 162 if (!mount_points->RegisterFileSystem( |
| 153 mount_point_name, storage::kFileSystemTypeProvided, | 163 mount_point_name, storage::kFileSystemTypeProvided, |
| 154 storage::FileSystemMountOption( | 164 storage::FileSystemMountOption( |
| 155 storage::FlushPolicy::FLUSH_ON_COMPLETION), | 165 storage::FlushPolicy::FLUSH_ON_COMPLETION), |
| 156 mount_path)) { | 166 mount_path)) { |
| 157 FOR_EACH_OBSERVER( | 167 FOR_EACH_OBSERVER( |
| 158 Observer, observers_, | 168 Observer, observers_, |
| 159 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, | 169 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, |
| 160 base::File::FILE_ERROR_INVALID_OPERATION)); | 170 base::File::FILE_ERROR_INVALID_OPERATION)); |
| 161 return base::File::FILE_ERROR_INVALID_OPERATION; | 171 return base::File::FILE_ERROR_INVALID_OPERATION; |
| 162 } | 172 } |
| 163 | 173 |
| 164 // Store the file system descriptor. Use the mount point name as the file | 174 // Store the file system descriptor. Use the mount point name as the file |
| 165 // system provider file system id. | 175 // system provider file system id. |
| 166 // Examples: | 176 // Examples: |
| 167 // file_system_id = hello_world | 177 // file_system_id = hello_world |
| 168 // mount_point_name = b33f1337-hello_world-5aa5 | 178 // mount_point_name = b33f1337-hello_world-5aa5 |
| 169 // writable = false | 179 // writable = false |
| 170 // supports_notify_tag = false | 180 // supports_notify_tag = false |
| 171 // mount_path = /provided/b33f1337-hello_world-5aa5 | 181 // mount_path = /provided/b33f1337-hello_world-5aa5 |
| 172 ProvidedFileSystemInfo file_system_info(extension_id, options, mount_path); | 182 ProvidedFileSystemInfo file_system_info(source_id, options, mount_path, |
| 183 source_type); |
| 173 | 184 |
| 174 ProvidedFileSystemInterface* file_system = | 185 ProvidedFileSystemInterface* file_system = NULL; |
| 175 file_system_factory_.Run(profile_, file_system_info); | 186 switch (source_type) { |
| 187 case Source_Type::extension: // file_system from extension |
| 188 file_system = file_system_factory_.Run(profile_, file_system_info); |
| 189 break; |
| 190 case Source_Type::plugin: // file_system from plugin |
| 191 file_system = CreateProvidedFileSystem<Source_Type::plugin>( |
| 192 profile_, file_system_info); |
| 193 break; |
| 194 } |
| 176 DCHECK(file_system); | 195 DCHECK(file_system); |
| 177 file_system_map_[FileSystemKey(extension_id, options.file_system_id)] = | 196 file_system_map_[FileSystemKey(source_id, options.file_system_id)] = |
| 178 file_system; | 197 file_system; |
| 179 mount_point_name_to_key_map_[mount_point_name] = | 198 mount_point_name_to_key_map_[mount_point_name] = |
| 180 FileSystemKey(extension_id, options.file_system_id); | 199 FileSystemKey(source_id, options.file_system_id); |
| 181 registry_->RememberFileSystem(file_system_info, *file_system->GetWatchers()); | 200 |
| 201 if (source_type == Source_Type::extension) |
| 202 registry_->RememberFileSystem(file_system_info, |
| 203 *file_system->GetWatchers()); |
| 182 | 204 |
| 183 FOR_EACH_OBSERVER(Observer, observers_, | 205 FOR_EACH_OBSERVER(Observer, observers_, |
| 184 OnProvidedFileSystemMount(file_system_info, context, | 206 OnProvidedFileSystemMount(file_system_info, context, |
| 185 base::File::FILE_OK)); | 207 base::File::FILE_OK)); |
| 186 | 208 |
| 187 return base::File::FILE_OK; | 209 return base::File::FILE_OK; |
| 188 } | 210 } |
| 189 | 211 |
| 190 base::File::Error Service::UnmountFileSystem(const std::string& extension_id, | 212 base::File::Error Service::UnmountFileSystem(const std::string& source_id, |
| 191 const std::string& file_system_id, | 213 const std::string& file_system_id, |
| 192 UnmountReason reason) { | 214 UnmountReason reason) { |
| 193 DCHECK(thread_checker_.CalledOnValidThread()); | 215 DCHECK(thread_checker_.CalledOnValidThread()); |
| 194 | 216 |
| 195 const ProvidedFileSystemMap::iterator file_system_it = | 217 const ProvidedFileSystemMap::iterator file_system_it = |
| 196 file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 218 file_system_map_.find(FileSystemKey(source_id, file_system_id)); |
| 197 if (file_system_it == file_system_map_.end()) { | 219 if (file_system_it == file_system_map_.end()) { |
| 198 const ProvidedFileSystemInfo empty_file_system_info; | 220 const ProvidedFileSystemInfo empty_file_system_info; |
| 199 FOR_EACH_OBSERVER( | 221 FOR_EACH_OBSERVER( |
| 200 Observer, | 222 Observer, |
| 201 observers_, | 223 observers_, |
| 202 OnProvidedFileSystemUnmount(empty_file_system_info, | 224 OnProvidedFileSystemUnmount(empty_file_system_info, |
| 203 base::File::FILE_ERROR_NOT_FOUND)); | 225 base::File::FILE_ERROR_NOT_FOUND)); |
| 204 return base::File::FILE_ERROR_NOT_FOUND; | 226 return base::File::FILE_ERROR_NOT_FOUND; |
| 205 } | 227 } |
| 206 | 228 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 222 return base::File::FILE_ERROR_INVALID_OPERATION; | 244 return base::File::FILE_ERROR_INVALID_OPERATION; |
| 223 } | 245 } |
| 224 | 246 |
| 225 FOR_EACH_OBSERVER( | 247 FOR_EACH_OBSERVER( |
| 226 Observer, | 248 Observer, |
| 227 observers_, | 249 observers_, |
| 228 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); | 250 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); |
| 229 | 251 |
| 230 mount_point_name_to_key_map_.erase(mount_point_name); | 252 mount_point_name_to_key_map_.erase(mount_point_name); |
| 231 | 253 |
| 232 if (reason == UNMOUNT_REASON_USER) { | 254 if (reason == UNMOUNT_REASON_USER && |
| 233 registry_->ForgetFileSystem(file_system_info.extension_id(), | 255 file_system_info.source_type()!=Source_Type::plugin) { |
| 256 registry_->ForgetFileSystem(file_system_info.source_id(), |
| 234 file_system_info.file_system_id()); | 257 file_system_info.file_system_id()); |
| 235 } | 258 } |
| 236 | 259 |
| 237 delete file_system_it->second; | 260 delete file_system_it->second; |
| 238 file_system_map_.erase(file_system_it); | 261 file_system_map_.erase(file_system_it); |
| 239 | 262 |
| 240 return base::File::FILE_OK; | 263 return base::File::FILE_OK; |
| 241 } | 264 } |
| 242 | 265 |
| 243 bool Service::RequestUnmount(const std::string& extension_id, | 266 bool Service::RequestUnmount(const std::string& extension_id, |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 } | 460 } |
| 438 | 461 |
| 439 void Service::OnWatcherListChanged( | 462 void Service::OnWatcherListChanged( |
| 440 const ProvidedFileSystemInfo& file_system_info, | 463 const ProvidedFileSystemInfo& file_system_info, |
| 441 const Watchers& watchers) { | 464 const Watchers& watchers) { |
| 442 registry_->RememberFileSystem(file_system_info, watchers); | 465 registry_->RememberFileSystem(file_system_info, watchers); |
| 443 } | 466 } |
| 444 | 467 |
| 445 } // namespace file_system_provider | 468 } // namespace file_system_provider |
| 446 } // namespace chromeos | 469 } // namespace chromeos |
| OLD | NEW |