| 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" | 
|  | 9 #include "base/prefs/scoped_user_pref_update.h" | 
| 8 #include "base/stl_util.h" | 10 #include "base/stl_util.h" | 
| 9 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" | 11 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" | 
| 10 #include "chrome/browser/chromeos/file_system_provider/observer.h" | 12 #include "chrome/browser/chromeos/file_system_provider/observer.h" | 
| 11 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" | 13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" | 
| 12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info
     .h" | 14 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info
     .h" | 
| 13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte
     rface.h" | 15 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte
     rface.h" | 
| 14 #include "chrome/browser/chromeos/file_system_provider/service_factory.h" | 16 #include "chrome/browser/chromeos/file_system_provider/service_factory.h" | 
| 15 #include "content/public/browser/browser_thread.h" | 17 #include "chrome/common/pref_names.h" | 
|  | 18 #include "components/pref_registry/pref_registry_syncable.h" | 
| 16 #include "extensions/browser/event_router.h" | 19 #include "extensions/browser/event_router.h" | 
| 17 #include "extensions/browser/extension_registry.h" | 20 #include "extensions/browser/extension_registry.h" | 
| 18 #include "extensions/browser/extension_system.h" | 21 #include "extensions/browser/extension_system.h" | 
| 19 #include "webkit/browser/fileapi/external_mount_points.h" | 22 #include "webkit/browser/fileapi/external_mount_points.h" | 
| 20 | 23 | 
| 21 using content::BrowserThread; |  | 
| 22 |  | 
| 23 namespace chromeos { | 24 namespace chromeos { | 
| 24 namespace file_system_provider { | 25 namespace file_system_provider { | 
| 25 namespace { | 26 namespace { | 
| 26 | 27 | 
| 27 // Maximum number of file systems to be mounted in the same time, per profile. | 28 // Maximum number of file systems to be mounted in the same time, per profile. | 
| 28 const size_t kMaxFileSystems = 16; | 29 const size_t kMaxFileSystems = 16; | 
| 29 | 30 | 
| 30 // Default factory for provided file systems. The |event_router| must not be | 31 // Default factory for provided file systems. The |event_router| must not be | 
| 31 // NULL. | 32 // NULL. | 
| 32 ProvidedFileSystemInterface* CreateProvidedFileSystem( | 33 ProvidedFileSystemInterface* CreateProvidedFileSystem( | 
| 33     extensions::EventRouter* event_router, | 34     extensions::EventRouter* event_router, | 
| 34     const ProvidedFileSystemInfo& file_system_info) { | 35     const ProvidedFileSystemInfo& file_system_info) { | 
| 35   DCHECK(event_router); | 36   DCHECK(event_router); | 
| 36   return new ProvidedFileSystem(event_router, file_system_info); | 37   return new ProvidedFileSystem(event_router, file_system_info); | 
| 37 } | 38 } | 
| 38 | 39 | 
| 39 }  // namespace | 40 }  // namespace | 
| 40 | 41 | 
|  | 42 const char kPrefKeyFileSystemId[] = "file-system-id"; | 
|  | 43 const char kPrefKeyFileSystemName[] = "file-system-name"; | 
|  | 44 | 
|  | 45 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { | 
|  | 46   registry->RegisterDictionaryPref( | 
|  | 47       prefs::kFileSystemProviderMounted, | 
|  | 48       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 
|  | 49 } | 
|  | 50 | 
| 41 Service::Service(Profile* profile, | 51 Service::Service(Profile* profile, | 
| 42                  extensions::ExtensionRegistry* extension_registry) | 52                  extensions::ExtensionRegistry* extension_registry) | 
| 43     : profile_(profile), | 53     : profile_(profile), | 
| 44       extension_registry_(extension_registry), | 54       extension_registry_(extension_registry), | 
| 45       file_system_factory_(base::Bind(CreateProvidedFileSystem)), | 55       file_system_factory_(base::Bind(CreateProvidedFileSystem)), | 
| 46       weak_ptr_factory_(this) { | 56       weak_ptr_factory_(this) { | 
| 47   extension_registry_->AddObserver(this); | 57   extension_registry_->AddObserver(this); | 
| 48 } | 58 } | 
| 49 | 59 | 
| 50 Service::~Service() { | 60 Service::~Service() { | 
| 51   extension_registry_->RemoveObserver(this); | 61   extension_registry_->RemoveObserver(this); | 
|  | 62   RememberFileSystems(); | 
| 52 | 63 | 
| 53   ProvidedFileSystemMap::iterator it = file_system_map_.begin(); | 64   ProvidedFileSystemMap::iterator it = file_system_map_.begin(); | 
| 54   while (it != file_system_map_.end()) { | 65   while (it != file_system_map_.end()) { | 
| 55     const std::string file_system_id = | 66     const std::string file_system_id = | 
| 56         it->second->GetFileSystemInfo().file_system_id(); | 67         it->second->GetFileSystemInfo().file_system_id(); | 
| 57     const std::string extension_id = | 68     const std::string extension_id = | 
| 58         it->second->GetFileSystemInfo().extension_id(); | 69         it->second->GetFileSystemInfo().extension_id(); | 
| 59     ++it; | 70     ++it; | 
| 60     UnmountFileSystem(extension_id, file_system_id); | 71     UnmountFileSystem(extension_id, file_system_id); | 
| 61   } | 72   } | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 81 | 92 | 
| 82 void Service::SetFileSystemFactoryForTests( | 93 void Service::SetFileSystemFactoryForTests( | 
| 83     const FileSystemFactoryCallback& factory_callback) { | 94     const FileSystemFactoryCallback& factory_callback) { | 
| 84   DCHECK(!factory_callback.is_null()); | 95   DCHECK(!factory_callback.is_null()); | 
| 85   file_system_factory_ = factory_callback; | 96   file_system_factory_ = factory_callback; | 
| 86 } | 97 } | 
| 87 | 98 | 
| 88 bool Service::MountFileSystem(const std::string& extension_id, | 99 bool Service::MountFileSystem(const std::string& extension_id, | 
| 89                               const std::string& file_system_id, | 100                               const std::string& file_system_id, | 
| 90                               const std::string& file_system_name) { | 101                               const std::string& file_system_name) { | 
| 91   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 102   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 92 | 103 | 
| 93   // If already exists a file system provided by the same extension with this | 104   // If already exists a file system provided by the same extension with this | 
| 94   // id, then abort. | 105   // id, then abort. | 
| 95   if (GetProvidedFileSystem(extension_id, file_system_id)) { | 106   if (GetProvidedFileSystem(extension_id, file_system_id)) { | 
| 96     FOR_EACH_OBSERVER(Observer, | 107     FOR_EACH_OBSERVER(Observer, | 
| 97                       observers_, | 108                       observers_, | 
| 98                       OnProvidedFileSystemMount(ProvidedFileSystemInfo(), | 109                       OnProvidedFileSystemMount(ProvidedFileSystemInfo(), | 
| 99                                                 base::File::FILE_ERROR_EXISTS)); | 110                                                 base::File::FILE_ERROR_EXISTS)); | 
| 100     return false; | 111     return false; | 
| 101   } | 112   } | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 154   FOR_EACH_OBSERVER( | 165   FOR_EACH_OBSERVER( | 
| 155       Observer, | 166       Observer, | 
| 156       observers_, | 167       observers_, | 
| 157       OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); | 168       OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); | 
| 158 | 169 | 
| 159   return true; | 170   return true; | 
| 160 } | 171 } | 
| 161 | 172 | 
| 162 bool Service::UnmountFileSystem(const std::string& extension_id, | 173 bool Service::UnmountFileSystem(const std::string& extension_id, | 
| 163                                 const std::string& file_system_id) { | 174                                 const std::string& file_system_id) { | 
| 164   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 175   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 165 | 176 | 
| 166   const ProvidedFileSystemMap::iterator file_system_it = | 177   const ProvidedFileSystemMap::iterator file_system_it = | 
| 167       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 178       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 
| 168   if (file_system_it == file_system_map_.end()) { | 179   if (file_system_it == file_system_map_.end()) { | 
| 169     const ProvidedFileSystemInfo empty_file_system_info; | 180     const ProvidedFileSystemInfo empty_file_system_info; | 
| 170     FOR_EACH_OBSERVER( | 181     FOR_EACH_OBSERVER( | 
| 171         Observer, | 182         Observer, | 
| 172         observers_, | 183         observers_, | 
| 173         OnProvidedFileSystemUnmount(empty_file_system_info, | 184         OnProvidedFileSystemUnmount(empty_file_system_info, | 
| 174                                     base::File::FILE_ERROR_NOT_FOUND)); | 185                                     base::File::FILE_ERROR_NOT_FOUND)); | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 201   mount_point_name_to_key_map_.erase(mount_point_name); | 212   mount_point_name_to_key_map_.erase(mount_point_name); | 
| 202 | 213 | 
| 203   delete file_system_it->second; | 214   delete file_system_it->second; | 
| 204   file_system_map_.erase(file_system_it); | 215   file_system_map_.erase(file_system_it); | 
| 205 | 216 | 
| 206   return true; | 217   return true; | 
| 207 } | 218 } | 
| 208 | 219 | 
| 209 bool Service::RequestUnmount(const std::string& extension_id, | 220 bool Service::RequestUnmount(const std::string& extension_id, | 
| 210                              const std::string& file_system_id) { | 221                              const std::string& file_system_id) { | 
| 211   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 222   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 212 | 223 | 
| 213   ProvidedFileSystemMap::iterator file_system_it = | 224   ProvidedFileSystemMap::iterator file_system_it = | 
| 214       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 225       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 
| 215   if (file_system_it == file_system_map_.end()) | 226   if (file_system_it == file_system_map_.end()) | 
| 216     return false; | 227     return false; | 
| 217 | 228 | 
| 218   file_system_it->second->RequestUnmount( | 229   file_system_it->second->RequestUnmount( | 
| 219       base::Bind(&Service::OnRequestUnmountStatus, | 230       base::Bind(&Service::OnRequestUnmountStatus, | 
| 220                  weak_ptr_factory_.GetWeakPtr(), | 231                  weak_ptr_factory_.GetWeakPtr(), | 
| 221                  file_system_it->second->GetFileSystemInfo())); | 232                  file_system_it->second->GetFileSystemInfo())); | 
| 222   return true; | 233   return true; | 
| 223 } | 234 } | 
| 224 | 235 | 
| 225 std::vector<ProvidedFileSystemInfo> Service::GetProvidedFileSystemInfoList() { | 236 std::vector<ProvidedFileSystemInfo> Service::GetProvidedFileSystemInfoList() { | 
| 226   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 237   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 227 | 238 | 
| 228   std::vector<ProvidedFileSystemInfo> result; | 239   std::vector<ProvidedFileSystemInfo> result; | 
| 229   for (ProvidedFileSystemMap::const_iterator it = file_system_map_.begin(); | 240   for (ProvidedFileSystemMap::const_iterator it = file_system_map_.begin(); | 
| 230        it != file_system_map_.end(); | 241        it != file_system_map_.end(); | 
| 231        ++it) { | 242        ++it) { | 
| 232     result.push_back(it->second->GetFileSystemInfo()); | 243     result.push_back(it->second->GetFileSystemInfo()); | 
| 233   } | 244   } | 
| 234   return result; | 245   return result; | 
| 235 } | 246 } | 
| 236 | 247 | 
| 237 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( | 248 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( | 
| 238     const std::string& extension_id, | 249     const std::string& extension_id, | 
| 239     const std::string& file_system_id) { | 250     const std::string& file_system_id) { | 
| 240   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 251   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 241 | 252 | 
| 242   const ProvidedFileSystemMap::const_iterator file_system_it = | 253   const ProvidedFileSystemMap::const_iterator file_system_it = | 
| 243       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 254       file_system_map_.find(FileSystemKey(extension_id, file_system_id)); | 
| 244   if (file_system_it == file_system_map_.end()) | 255   if (file_system_it == file_system_map_.end()) | 
| 245     return NULL; | 256     return NULL; | 
| 246 | 257 | 
| 247   return file_system_it->second; | 258   return file_system_it->second; | 
| 248 } | 259 } | 
| 249 | 260 | 
| 250 void Service::OnExtensionUnloaded( | 261 void Service::OnExtensionUnloaded( | 
| 251     content::BrowserContext* browser_context, | 262     content::BrowserContext* browser_context, | 
| 252     const extensions::Extension* extension, | 263     const extensions::Extension* extension, | 
| 253     extensions::UnloadedExtensionInfo::Reason reason) { | 264     extensions::UnloadedExtensionInfo::Reason reason) { | 
|  | 265   // If the reason is not a profile shutdown, then forget the mounted file | 
|  | 266   // systems from preferences. | 
|  | 267   if (reason != extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN) | 
|  | 268     ForgetFileSystems(extension->id()); | 
|  | 269 | 
| 254   // Unmount all of the provided file systems associated with this extension. | 270   // Unmount all of the provided file systems associated with this extension. | 
| 255   ProvidedFileSystemMap::iterator it = file_system_map_.begin(); | 271   ProvidedFileSystemMap::iterator it = file_system_map_.begin(); | 
| 256   while (it != file_system_map_.end()) { | 272   while (it != file_system_map_.end()) { | 
| 257     const ProvidedFileSystemInfo& file_system_info = | 273     const ProvidedFileSystemInfo& file_system_info = | 
| 258         it->second->GetFileSystemInfo(); | 274         it->second->GetFileSystemInfo(); | 
| 259     // Advance the iterator beforehand, otherwise it will become invalidated | 275     // Advance the iterator beforehand, otherwise it will become invalidated | 
| 260     // by the UnmountFileSystem() call. | 276     // by the UnmountFileSystem() call. | 
| 261     ++it; | 277     ++it; | 
| 262     if (file_system_info.extension_id() == extension->id()) { | 278     if (file_system_info.extension_id() == extension->id()) { | 
| 263       bool result = UnmountFileSystem(file_system_info.extension_id(), | 279       bool result = UnmountFileSystem(file_system_info.extension_id(), | 
| 264                                       file_system_info.file_system_id()); | 280                                       file_system_info.file_system_id()); | 
| 265       DCHECK(result); | 281       DCHECK(result); | 
| 266     } | 282     } | 
| 267   } | 283   } | 
| 268 } | 284 } | 
| 269 | 285 | 
|  | 286 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, | 
|  | 287                                 const extensions::Extension* extension) { | 
|  | 288   RestoreFileSystems(extension->id()); | 
|  | 289 } | 
|  | 290 | 
| 270 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( | 291 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( | 
| 271     const std::string& mount_point_name) { | 292     const std::string& mount_point_name) { | 
| 272   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 293   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 273 | 294 | 
| 274   const MountPointNameToKeyMap::const_iterator mapping_it = | 295   const MountPointNameToKeyMap::const_iterator mapping_it = | 
| 275       mount_point_name_to_key_map_.find(mount_point_name); | 296       mount_point_name_to_key_map_.find(mount_point_name); | 
| 276   if (mapping_it == mount_point_name_to_key_map_.end()) | 297   if (mapping_it == mount_point_name_to_key_map_.end()) | 
| 277     return NULL; | 298     return NULL; | 
| 278 | 299 | 
| 279   const ProvidedFileSystemMap::const_iterator file_system_it = | 300   const ProvidedFileSystemMap::const_iterator file_system_it = | 
| 280       file_system_map_.find(mapping_it->second); | 301       file_system_map_.find(mapping_it->second); | 
| 281   if (file_system_it == file_system_map_.end()) | 302   if (file_system_it == file_system_map_.end()) | 
| 282     return NULL; | 303     return NULL; | 
| 283 | 304 | 
| 284   return file_system_it->second; | 305   return file_system_it->second; | 
| 285 } | 306 } | 
| 286 | 307 | 
| 287 void Service::OnRequestUnmountStatus( | 308 void Service::OnRequestUnmountStatus( | 
| 288     const ProvidedFileSystemInfo& file_system_info, | 309     const ProvidedFileSystemInfo& file_system_info, | 
| 289     base::File::Error error) { | 310     base::File::Error error) { | 
| 290   // Notify observers about failure in unmounting, since mount() will not be | 311   // Notify observers about failure in unmounting, since mount() will not be | 
| 291   // called by the provided file system. In case of success mount() will be | 312   // called by the provided file system. In case of success mount() will be | 
| 292   // invoked, and observers notified, so there is no need to call them now. | 313   // invoked, and observers notified, so there is no need to call them now. | 
| 293   if (error != base::File::FILE_OK) { | 314   if (error != base::File::FILE_OK) { | 
| 294     FOR_EACH_OBSERVER(Observer, | 315     FOR_EACH_OBSERVER(Observer, | 
| 295                       observers_, | 316                       observers_, | 
| 296                       OnProvidedFileSystemUnmount(file_system_info, error)); | 317                       OnProvidedFileSystemUnmount(file_system_info, error)); | 
| 297   } | 318   } | 
| 298 } | 319 } | 
| 299 | 320 | 
|  | 321 void Service::RememberFileSystems() { | 
|  | 322   base::DictionaryValue extensions; | 
|  | 323   const std::vector<ProvidedFileSystemInfo> file_system_info_list = | 
|  | 324       GetProvidedFileSystemInfoList(); | 
|  | 325 | 
|  | 326   for (std::vector<ProvidedFileSystemInfo>::const_iterator it = | 
|  | 327            file_system_info_list.begin(); | 
|  | 328        it != file_system_info_list.end(); | 
|  | 329        ++it) { | 
|  | 330     base::ListValue* file_systems = NULL; | 
|  | 331     if (!extensions.GetList(it->extension_id(), &file_systems)) { | 
|  | 332       file_systems = new base::ListValue(); | 
|  | 333       extensions.Set(it->extension_id(), file_systems); | 
|  | 334     } | 
|  | 335 | 
|  | 336     base::DictionaryValue* file_system = new base::DictionaryValue(); | 
|  | 337     file_system->SetString(kPrefKeyFileSystemId, it->file_system_id()); | 
|  | 338     file_system->SetString(kPrefKeyFileSystemName, it->file_system_name()); | 
|  | 339     file_systems->Append(file_system); | 
|  | 340   } | 
|  | 341 | 
|  | 342   PrefService* pref_service = profile_->GetPrefs(); | 
|  | 343   DCHECK(pref_service); | 
|  | 344   pref_service->Set(prefs::kFileSystemProviderMounted, extensions); | 
|  | 345   pref_service->CommitPendingWrite(); | 
|  | 346 } | 
|  | 347 | 
|  | 348 void Service::ForgetFileSystems(const std::string& extension_id) { | 
|  | 349   PrefService* pref_service = profile_->GetPrefs(); | 
|  | 350   DCHECK(pref_service); | 
|  | 351 | 
|  | 352   DictionaryPrefUpdate update(pref_service, prefs::kFileSystemProviderMounted); | 
|  | 353   base::DictionaryValue* extensions = update.Get(); | 
|  | 354   DCHECK(extensions); | 
|  | 355 | 
|  | 356   extensions->Remove(extension_id, NULL); | 
|  | 357 } | 
|  | 358 | 
|  | 359 void Service::RestoreFileSystems(const std::string& extension_id) { | 
|  | 360   PrefService* pref_service = profile_->GetPrefs(); | 
|  | 361   DCHECK(pref_service); | 
|  | 362 | 
|  | 363   const base::DictionaryValue* extensions = | 
|  | 364       pref_service->GetDictionary(prefs::kFileSystemProviderMounted); | 
|  | 365   DCHECK(extensions); | 
|  | 366 | 
|  | 367   const base::ListValue* file_systems = NULL; | 
|  | 368 | 
|  | 369   if (!extensions->GetList(extension_id, &file_systems)) | 
|  | 370     return; | 
|  | 371 | 
|  | 372   for (size_t i = 0; i < file_systems->GetSize(); ++i) { | 
|  | 373     const base::DictionaryValue* file_system = NULL; | 
|  | 374     file_systems->GetDictionary(i, &file_system); | 
|  | 375     DCHECK(file_system); | 
|  | 376 | 
|  | 377     std::string file_system_id; | 
|  | 378     file_system->GetString(kPrefKeyFileSystemId, &file_system_id); | 
|  | 379     DCHECK(!file_system_id.empty()); | 
|  | 380 | 
|  | 381     std::string file_system_name; | 
|  | 382     file_system->GetString(kPrefKeyFileSystemName, &file_system_name); | 
|  | 383     DCHECK(!file_system_name.empty()); | 
|  | 384 | 
|  | 385     if (file_system_id.empty() || file_system_name.empty()) { | 
|  | 386       LOG(ERROR) | 
|  | 387           << "Malformed provided file system information in preferences."; | 
|  | 388       continue; | 
|  | 389     } | 
|  | 390 | 
|  | 391     const bool result = | 
|  | 392         MountFileSystem(extension_id, file_system_id, file_system_name); | 
|  | 393     if (!result) { | 
|  | 394       LOG(ERROR) << "Failed to restore a provided file system from " | 
|  | 395                  << "preferences: " << extension_id << ", " << file_system_id | 
|  | 396                  << ", " << file_system_name << "."; | 
|  | 397     } | 
|  | 398   } | 
|  | 399 } | 
|  | 400 | 
| 300 }  // namespace file_system_provider | 401 }  // namespace file_system_provider | 
| 301 }  // namespace chromeos | 402 }  // namespace chromeos | 
| OLD | NEW | 
|---|