service.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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/strings/string_number_conversions.h" 9#include "chrome/browser/chromeos/file_system_provider/observer.h" 10#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" 11#include "chrome/browser/chromeos/file_system_provider/service_factory.h" 12#include "chrome/browser/chromeos/login/user.h" 13#include "chrome/browser/chromeos/login/user_manager.h" 14#include "content/public/browser/browser_thread.h" 15#include "webkit/browser/fileapi/external_mount_points.h" 16 17namespace chromeos { 18namespace file_system_provider { 19namespace { 20 21// Root mount path for all of the provided file systems. 22const base::FilePath::CharType kProvidedMountPointRoot[] = 23 FILE_PATH_LITERAL("/provided"); 24 25// Maximum number of file systems to be mounted in the same time, per profile. 26const size_t kMaxFileSystems = 16; 27 28// Constructs a safe mount point path for the provided file system represented 29// by |file_system_handle|. The handle is a numeric part of the file system id. 30base::FilePath GetMountPointPath(Profile* profile, 31 std::string extension_id, 32 int file_system_id) { 33 chromeos::User* const user = 34 chromeos::UserManager::IsInitialized() 35 ? chromeos::UserManager::Get()->GetUserByProfile( 36 profile->GetOriginalProfile()) 37 : NULL; 38 const std::string user_suffix = user ? "-" + user->username_hash() : ""; 39 return base::FilePath(kProvidedMountPointRoot).AppendASCII( 40 extension_id + "-" + base::IntToString(file_system_id) + user_suffix); 41} 42 43} // namespace 44 45Service::Service(Profile* profile) : profile_(profile), next_id_(1) {} 46 47Service::~Service() {} 48 49// static 50Service* Service::Get(content::BrowserContext* context) { 51 return ServiceFactory::Get(context); 52} 53 54void Service::AddObserver(Observer* observer) { 55 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 56 DCHECK(observer); 57 observers_.AddObserver(observer); 58} 59 60void Service::RemoveObserver(Observer* observer) { 61 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 62 DCHECK(observer); 63 observers_.RemoveObserver(observer); 64} 65 66int Service::RegisterFileSystem(const std::string& extension_id, 67 const std::string& file_system_name) { 68 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 69 70 // Restrict number of file systems to prevent system abusing. 71 if (file_systems_.size() + 1 > kMaxFileSystems) 72 return 0; 73 74 // The file system id is unique per service, so per profile. 75 int file_system_id = next_id_; 76 77 fileapi::ExternalMountPoints* const mount_points = 78 fileapi::ExternalMountPoints::GetSystemInstance(); 79 DCHECK(mount_points); 80 81 // The mount point path and name are unique per system, since they are system 82 // wide. This is necessary for copying between profiles. 83 const base::FilePath& mount_point_path = 84 GetMountPointPath(profile_, extension_id, file_system_id); 85 const std::string mount_point_name = 86 mount_point_path.BaseName().AsUTF8Unsafe(); 87 88 if (!mount_points->RegisterFileSystem(mount_point_name, 89 fileapi::kFileSystemTypeProvided, 90 fileapi::FileSystemMountOption(), 91 mount_point_path)) { 92 return 0; 93 } 94 95 // Store the file system descriptor. Use the mount point name as the file 96 // system provider file system id. 97 // Examples: 98 // file_system_id = 41 99 // mount_point_name = file_system_id = b33f1337-41-5aa5 100 // mount_point_path = /provided/b33f1337-41-5aa5 101 ProvidedFileSystem file_system( 102 extension_id, file_system_id, file_system_name, mount_point_path); 103 file_systems_[file_system_id] = file_system; 104 105 FOR_EACH_OBSERVER( 106 Observer, observers_, OnProvidedFileSystemRegistered(file_system)); 107 108 next_id_++; 109 return file_system_id; 110} 111 112bool Service::UnregisterFileSystem(const std::string& extension_id, 113 int file_system_id) { 114 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 115 116 FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id); 117 if (file_system_it == file_systems_.end() || 118 file_system_it->second.extension_id() != extension_id) { 119 return false; 120 } 121 122 fileapi::ExternalMountPoints* const mount_points = 123 fileapi::ExternalMountPoints::GetSystemInstance(); 124 DCHECK(mount_points); 125 126 const std::string mount_point_name = 127 file_system_it->second.mount_path().BaseName().value(); 128 if (!mount_points->RevokeFileSystem(mount_point_name)) 129 return false; 130 131 FOR_EACH_OBSERVER(Observer, 132 observers_, 133 OnProvidedFileSystemUnregistered(file_system_it->second)); 134 135 file_systems_.erase(file_system_it); 136 return true; 137} 138 139std::vector<ProvidedFileSystem> Service::GetRegisteredFileSystems() { 140 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 141 142 std::vector<ProvidedFileSystem> result; 143 for (FileSystemMap::const_iterator it = file_systems_.begin(); 144 it != file_systems_.end(); 145 ++it) { 146 result.push_back(it->second); 147 } 148 return result; 149} 150 151} // namespace file_system_provider 152} // namespace chromeos 153