Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: chrome/browser/chromeos/file_system_provider/service.cc

Issue 1148293006: Rename service/service_factory of file_system_provider and launcher_search_provider (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lsp Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/file_system_provider/service.h"
6
7 #include "base/files/file_path.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/stl_util.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
13 #include "chrome/browser/chromeos/file_system_provider/observer.h"
14 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
15 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info .h"
16 #include "chrome/browser/chromeos/file_system_provider/registry.h"
17 #include "chrome/browser/chromeos/file_system_provider/registry_interface.h"
18 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
19 #include "chrome/browser/chromeos/file_system_provider/throttled_file_system.h"
20 #include "extensions/browser/event_router.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/permissions/api_permission.h"
24 #include "extensions/common/permissions/permissions_data.h"
25 #include "storage/browser/fileapi/external_mount_points.h"
26 #include "storage/common/fileapi/file_system_mount_option.h"
27
28 namespace chromeos {
29 namespace file_system_provider {
30 namespace {
31
32 // Maximum number of file systems to be mounted in the same time, per profile.
33 const size_t kMaxFileSystems = 16;
34
35 // Default factory for provided file systems. |profile| must not be NULL.
36 ProvidedFileSystemInterface* CreateProvidedFileSystem(
37 Profile* profile,
38 const ProvidedFileSystemInfo& file_system_info) {
39 DCHECK(profile);
40 return new ThrottledFileSystem(
41 make_scoped_ptr(new ProvidedFileSystem(profile, file_system_info)));
42 }
43
44 } // namespace
45
46 ProvidingExtensionInfo::ProvidingExtensionInfo() {
47 }
48
49 ProvidingExtensionInfo::~ProvidingExtensionInfo() {
50 }
51
52 Service::Service(Profile* profile,
53 extensions::ExtensionRegistry* extension_registry)
54 : profile_(profile),
55 extension_registry_(extension_registry),
56 file_system_factory_(base::Bind(&CreateProvidedFileSystem)),
57 registry_(new Registry(profile)),
58 weak_ptr_factory_(this) {
59 extension_registry_->AddObserver(this);
60 }
61
62 Service::~Service() {
63 extension_registry_->RemoveObserver(this);
64
65 // Provided file systems should be already unmounted because of receiving
66 // OnExtensionUnload calls for each installed extension. However, for tests
67 // we may still have mounted extensions.
68 // TODO(mtomasz): Create a TestingService class and remove this code.
69 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
70 while (it != file_system_map_.end()) {
71 const std::string file_system_id =
72 it->second->GetFileSystemInfo().file_system_id();
73 const std::string extension_id =
74 it->second->GetFileSystemInfo().extension_id();
75 ++it;
76 const base::File::Error unmount_result = UnmountFileSystem(
77 extension_id, file_system_id, UNMOUNT_REASON_SHUTDOWN);
78 DCHECK_EQ(base::File::FILE_OK, unmount_result);
79 }
80
81 DCHECK_EQ(0u, file_system_map_.size());
82 STLDeleteValues(&file_system_map_);
83 }
84
85 // static
86 Service* Service::Get(content::BrowserContext* context) {
87 return ServiceFactory::Get(context);
88 }
89
90 void Service::AddObserver(Observer* observer) {
91 DCHECK(observer);
92 observers_.AddObserver(observer);
93 }
94
95 void Service::RemoveObserver(Observer* observer) {
96 DCHECK(observer);
97 observers_.RemoveObserver(observer);
98 }
99
100 void Service::SetFileSystemFactoryForTesting(
101 const FileSystemFactoryCallback& factory_callback) {
102 DCHECK(!factory_callback.is_null());
103 file_system_factory_ = factory_callback;
104 }
105
106 void Service::SetRegistryForTesting(scoped_ptr<RegistryInterface> registry) {
107 DCHECK(registry);
108 registry_.reset(registry.release());
109 }
110
111 base::File::Error Service::MountFileSystem(const std::string& extension_id,
112 const MountOptions& options) {
113 return MountFileSystemInternal(extension_id, options, MOUNT_CONTEXT_USER);
114 }
115
116 base::File::Error Service::MountFileSystemInternal(
117 const std::string& extension_id,
118 const MountOptions& options,
119 MountContext context) {
120 DCHECK(thread_checker_.CalledOnValidThread());
121
122 // If already exists a file system provided by the same extension with this
123 // id, then abort.
124 if (GetProvidedFileSystem(extension_id, options.file_system_id)) {
125 FOR_EACH_OBSERVER(
126 Observer, observers_,
127 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context,
128 base::File::FILE_ERROR_EXISTS));
129 return base::File::FILE_ERROR_EXISTS;
130 }
131
132 // Restrict number of file systems to prevent system abusing.
133 if (file_system_map_.size() + 1 > kMaxFileSystems) {
134 FOR_EACH_OBSERVER(
135 Observer, observers_,
136 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context,
137 base::File::FILE_ERROR_TOO_MANY_OPENED));
138 return base::File::FILE_ERROR_TOO_MANY_OPENED;
139 }
140
141 storage::ExternalMountPoints* const mount_points =
142 storage::ExternalMountPoints::GetSystemInstance();
143 DCHECK(mount_points);
144
145 // The mount point path and name are unique per system, since they are system
146 // wide. This is necessary for copying between profiles.
147 const base::FilePath& mount_path =
148 util::GetMountPath(profile_, extension_id, options.file_system_id);
149 const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe();
150
151 if (!mount_points->RegisterFileSystem(
152 mount_point_name, storage::kFileSystemTypeProvided,
153 storage::FileSystemMountOption(
154 storage::FlushPolicy::FLUSH_ON_COMPLETION),
155 mount_path)) {
156 FOR_EACH_OBSERVER(
157 Observer, observers_,
158 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context,
159 base::File::FILE_ERROR_INVALID_OPERATION));
160 return base::File::FILE_ERROR_INVALID_OPERATION;
161 }
162
163 ProvidingExtensionInfo provider_info;
164 // TODO(mtomasz): Set up a testing extension in unit tests.
165 GetProvidingExtensionInfo(extension_id, &provider_info);
166 // Store the file system descriptor. Use the mount point name as the file
167 // system provider file system id.
168 // Examples:
169 // file_system_id = hello_world
170 // mount_point_name = b33f1337-hello_world-5aa5
171 // writable = false
172 // supports_notify_tag = false
173 // mount_path = /provided/b33f1337-hello_world-5aa5
174 // configurable = true
175 // source = SOURCE_FILE
176 ProvidedFileSystemInfo file_system_info(
177 extension_id, options, mount_path,
178 provider_info.capabilities.configurable(),
179 provider_info.capabilities.source());
180
181 ProvidedFileSystemInterface* file_system =
182 file_system_factory_.Run(profile_, file_system_info);
183 DCHECK(file_system);
184 file_system_map_[FileSystemKey(extension_id, options.file_system_id)] =
185 file_system;
186 mount_point_name_to_key_map_[mount_point_name] =
187 FileSystemKey(extension_id, options.file_system_id);
188 registry_->RememberFileSystem(file_system_info, *file_system->GetWatchers());
189
190 FOR_EACH_OBSERVER(Observer, observers_,
191 OnProvidedFileSystemMount(file_system_info, context,
192 base::File::FILE_OK));
193
194 return base::File::FILE_OK;
195 }
196
197 base::File::Error Service::UnmountFileSystem(const std::string& extension_id,
198 const std::string& file_system_id,
199 UnmountReason reason) {
200 DCHECK(thread_checker_.CalledOnValidThread());
201
202 const ProvidedFileSystemMap::iterator file_system_it =
203 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
204 if (file_system_it == file_system_map_.end()) {
205 const ProvidedFileSystemInfo empty_file_system_info;
206 FOR_EACH_OBSERVER(
207 Observer,
208 observers_,
209 OnProvidedFileSystemUnmount(empty_file_system_info,
210 base::File::FILE_ERROR_NOT_FOUND));
211 return base::File::FILE_ERROR_NOT_FOUND;
212 }
213
214 storage::ExternalMountPoints* const mount_points =
215 storage::ExternalMountPoints::GetSystemInstance();
216 DCHECK(mount_points);
217
218 const ProvidedFileSystemInfo& file_system_info =
219 file_system_it->second->GetFileSystemInfo();
220
221 const std::string mount_point_name =
222 file_system_info.mount_path().BaseName().value();
223 if (!mount_points->RevokeFileSystem(mount_point_name)) {
224 FOR_EACH_OBSERVER(
225 Observer,
226 observers_,
227 OnProvidedFileSystemUnmount(file_system_info,
228 base::File::FILE_ERROR_INVALID_OPERATION));
229 return base::File::FILE_ERROR_INVALID_OPERATION;
230 }
231
232 FOR_EACH_OBSERVER(
233 Observer,
234 observers_,
235 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
236
237 mount_point_name_to_key_map_.erase(mount_point_name);
238
239 if (reason == UNMOUNT_REASON_USER) {
240 registry_->ForgetFileSystem(file_system_info.extension_id(),
241 file_system_info.file_system_id());
242 }
243
244 delete file_system_it->second;
245 file_system_map_.erase(file_system_it);
246
247 return base::File::FILE_OK;
248 }
249
250 bool Service::RequestUnmount(const std::string& extension_id,
251 const std::string& file_system_id) {
252 DCHECK(thread_checker_.CalledOnValidThread());
253
254 ProvidedFileSystemMap::iterator file_system_it =
255 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
256 if (file_system_it == file_system_map_.end())
257 return false;
258
259 file_system_it->second->RequestUnmount(
260 base::Bind(&Service::OnRequestUnmountStatus,
261 weak_ptr_factory_.GetWeakPtr(),
262 file_system_it->second->GetFileSystemInfo()));
263 return true;
264 }
265
266 bool Service::RequestMount(const std::string& extension_id) {
267 DCHECK(thread_checker_.CalledOnValidThread());
268
269 extensions::EventRouter* const event_router =
270 extensions::EventRouter::Get(profile_);
271 DCHECK(event_router);
272
273 if (!event_router->ExtensionHasEventListener(
274 extension_id, extensions::api::file_system_provider::
275 OnMountRequested::kEventName)) {
276 return false;
277 }
278
279 event_router->DispatchEventToExtension(
280 extension_id,
281 make_scoped_ptr(new extensions::Event(
282 extensions::api::file_system_provider::OnMountRequested::kEventName,
283 scoped_ptr<base::ListValue>(new base::ListValue()))));
284
285 return true;
286 }
287
288 std::vector<ProvidedFileSystemInfo> Service::GetProvidedFileSystemInfoList() {
289 DCHECK(thread_checker_.CalledOnValidThread());
290
291 std::vector<ProvidedFileSystemInfo> result;
292 for (ProvidedFileSystemMap::const_iterator it = file_system_map_.begin();
293 it != file_system_map_.end();
294 ++it) {
295 result.push_back(it->second->GetFileSystemInfo());
296 }
297 return result;
298 }
299
300 ProvidedFileSystemInterface* Service::GetProvidedFileSystem(
301 const std::string& extension_id,
302 const std::string& file_system_id) {
303 DCHECK(thread_checker_.CalledOnValidThread());
304
305 const ProvidedFileSystemMap::const_iterator file_system_it =
306 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
307 if (file_system_it == file_system_map_.end())
308 return NULL;
309
310 return file_system_it->second;
311 }
312
313 std::vector<ProvidingExtensionInfo> Service::GetProvidingExtensionInfoList()
314 const {
315 extensions::ExtensionRegistry* const registry =
316 extensions::ExtensionRegistry::Get(profile_);
317 DCHECK(registry);
318
319 std::vector<ProvidingExtensionInfo> result;
320 for (const auto& extension : registry->enabled_extensions()) {
321 ProvidingExtensionInfo info;
322 if (GetProvidingExtensionInfo(extension->id(), &info))
323 result.push_back(info);
324 }
325
326 return result;
327 }
328
329 bool Service::GetProvidingExtensionInfo(const std::string& extension_id,
330 ProvidingExtensionInfo* result) const {
331 DCHECK(result);
332 extensions::ExtensionRegistry* const registry =
333 extensions::ExtensionRegistry::Get(profile_);
334 DCHECK(registry);
335
336 const extensions::Extension* const extension = registry->GetExtensionById(
337 extension_id, extensions::ExtensionRegistry::ENABLED);
338 if (!extension ||
339 !extension->permissions_data()->HasAPIPermission(
340 extensions::APIPermission::kFileSystemProvider)) {
341 return false;
342 }
343
344 result->extension_id = extension->id();
345 result->name = extension->name();
346 const extensions::FileSystemProviderCapabilities* const capabilities =
347 extensions::FileSystemProviderCapabilities::Get(extension);
348 DCHECK(capabilities);
349 result->capabilities = *capabilities;
350
351 return true;
352 }
353
354 void Service::OnExtensionUnloaded(
355 content::BrowserContext* browser_context,
356 const extensions::Extension* extension,
357 extensions::UnloadedExtensionInfo::Reason reason) {
358 // Unmount all of the provided file systems associated with this extension.
359 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
360 while (it != file_system_map_.end()) {
361 const ProvidedFileSystemInfo& file_system_info =
362 it->second->GetFileSystemInfo();
363 // Advance the iterator beforehand, otherwise it will become invalidated
364 // by the UnmountFileSystem() call.
365 ++it;
366 if (file_system_info.extension_id() == extension->id()) {
367 const base::File::Error unmount_result = UnmountFileSystem(
368 file_system_info.extension_id(), file_system_info.file_system_id(),
369 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN
370 ? UNMOUNT_REASON_SHUTDOWN
371 : UNMOUNT_REASON_USER);
372 DCHECK_EQ(base::File::FILE_OK, unmount_result);
373 }
374 }
375 }
376
377 void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
378 const extensions::Extension* extension) {
379 scoped_ptr<RegistryInterface::RestoredFileSystems> restored_file_systems =
380 registry_->RestoreFileSystems(extension->id());
381
382 for (const auto& restored_file_system : *restored_file_systems) {
383 const base::File::Error result = MountFileSystemInternal(
384 restored_file_system.extension_id, restored_file_system.options,
385 MOUNT_CONTEXT_RESTORE);
386 if (result != base::File::FILE_OK) {
387 LOG(ERROR) << "Failed to restore a provided file system from "
388 << "registry: " << restored_file_system.extension_id << ", "
389 << restored_file_system.options.file_system_id << ", "
390 << restored_file_system.options.display_name << ".";
391 // Since remounting of the file system failed, then remove it from
392 // preferences to avoid remounting it over and over again with a failure.
393 registry_->ForgetFileSystem(restored_file_system.extension_id,
394 restored_file_system.options.file_system_id);
395 continue;
396 }
397
398 ProvidedFileSystemInterface* const file_system =
399 GetProvidedFileSystem(restored_file_system.extension_id,
400 restored_file_system.options.file_system_id);
401 DCHECK(file_system);
402 file_system->GetWatchers()->insert(restored_file_system.watchers.begin(),
403 restored_file_system.watchers.end());
404 }
405 }
406
407 ProvidedFileSystemInterface* Service::GetProvidedFileSystem(
408 const std::string& mount_point_name) {
409 DCHECK(thread_checker_.CalledOnValidThread());
410
411 const MountPointNameToKeyMap::const_iterator mapping_it =
412 mount_point_name_to_key_map_.find(mount_point_name);
413 if (mapping_it == mount_point_name_to_key_map_.end())
414 return NULL;
415
416 const ProvidedFileSystemMap::const_iterator file_system_it =
417 file_system_map_.find(mapping_it->second);
418 if (file_system_it == file_system_map_.end())
419 return NULL;
420
421 return file_system_it->second;
422 }
423
424 void Service::OnRequestUnmountStatus(
425 const ProvidedFileSystemInfo& file_system_info,
426 base::File::Error error) {
427 // Notify observers about failure in unmounting, since mount() will not be
428 // called by the provided file system. In case of success mount() will be
429 // invoked, and observers notified, so there is no need to call them now.
430 if (error != base::File::FILE_OK) {
431 FOR_EACH_OBSERVER(Observer,
432 observers_,
433 OnProvidedFileSystemUnmount(file_system_info, error));
434 }
435 }
436
437 void Service::OnWatcherChanged(const ProvidedFileSystemInfo& file_system_info,
438 const Watcher& watcher,
439 storage::WatcherManager::ChangeType change_type,
440 const Changes& changes,
441 const base::Closure& callback) {
442 callback.Run();
443 }
444
445 void Service::OnWatcherTagUpdated(
446 const ProvidedFileSystemInfo& file_system_info,
447 const Watcher& watcher) {
448 PrefService* const pref_service = profile_->GetPrefs();
449 DCHECK(pref_service);
450
451 registry_->UpdateWatcherTag(file_system_info, watcher);
452 }
453
454 void Service::OnWatcherListChanged(
455 const ProvidedFileSystemInfo& file_system_info,
456 const Watchers& watchers) {
457 registry_->RememberFileSystem(file_system_info, watchers);
458 }
459
460 } // namespace file_system_provider
461 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698