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 |