Chromium Code Reviews| 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" |
| 11 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" | 11 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" |
| 12 #include "chrome/browser/chromeos/file_system_provider/observer.h" | 12 #include "chrome/browser/chromeos/file_system_provider/observer.h" |
| 13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" | 13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" |
| 14 #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" |
| 15 #include "chrome/browser/chromeos/file_system_provider/registry.h" | |
| 16 #include "chrome/browser/chromeos/file_system_provider/registry_interface.h" | |
| 15 #include "chrome/browser/chromeos/file_system_provider/service_factory.h" | 17 #include "chrome/browser/chromeos/file_system_provider/service_factory.h" |
| 16 #include "chrome/common/pref_names.h" | |
| 17 #include "components/pref_registry/pref_registry_syncable.h" | |
| 18 #include "extensions/browser/extension_registry.h" | 18 #include "extensions/browser/extension_registry.h" |
| 19 #include "extensions/browser/extension_system.h" | 19 #include "extensions/browser/extension_system.h" |
| 20 #include "storage/browser/fileapi/external_mount_points.h" | 20 #include "storage/browser/fileapi/external_mount_points.h" |
| 21 | 21 |
| 22 namespace chromeos { | 22 namespace chromeos { |
| 23 namespace file_system_provider { | 23 namespace file_system_provider { |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // Maximum number of file systems to be mounted in the same time, per profile. | 26 // Maximum number of file systems to be mounted in the same time, per profile. |
| 27 const size_t kMaxFileSystems = 16; | 27 const size_t kMaxFileSystems = 16; |
| 28 | 28 |
| 29 // Default factory for provided file systems. |profile| must not be NULL. | 29 // Default factory for provided file systems. |profile| must not be NULL. |
| 30 ProvidedFileSystemInterface* CreateProvidedFileSystem( | 30 ProvidedFileSystemInterface* CreateProvidedFileSystem( |
| 31 Profile* profile, | 31 Profile* profile, |
| 32 const ProvidedFileSystemInfo& file_system_info) { | 32 const ProvidedFileSystemInfo& file_system_info) { |
| 33 DCHECK(profile); | 33 DCHECK(profile); |
| 34 return new ProvidedFileSystem(profile, file_system_info); | 34 return new ProvidedFileSystem(profile, file_system_info); |
| 35 } | 35 } |
| 36 | 36 |
| 37 } // namespace | 37 } // namespace |
| 38 | 38 |
| 39 const char kPrefKeyFileSystemId[] = "file-system-id"; | |
| 40 const char kPrefKeyDisplayName[] = "display-name"; | |
| 41 const char kPrefKeyWritable[] = "writable"; | |
| 42 const char kPrefKeySupportsNotifyTag[] = "supports-notify-tag"; | |
| 43 const char kPrefKeyObservedEntries[] = "observed-entries"; | |
| 44 const char kPrefKeyObservedEntryEntryPath[] = "entry-path"; | |
| 45 const char kPrefKeyObservedEntryRecursive[] = "recursive"; | |
| 46 const char kPrefKeyObservedEntryLastTag[] = "last-tag"; | |
| 47 | |
| 48 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { | |
| 49 registry->RegisterDictionaryPref( | |
| 50 prefs::kFileSystemProviderMounted, | |
| 51 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
| 52 } | |
| 53 | |
| 54 Service::Service(Profile* profile, | 39 Service::Service(Profile* profile, |
| 55 extensions::ExtensionRegistry* extension_registry) | 40 extensions::ExtensionRegistry* extension_registry) |
| 56 : profile_(profile), | 41 : profile_(profile), |
| 57 extension_registry_(extension_registry), | 42 extension_registry_(extension_registry), |
| 58 file_system_factory_(base::Bind(CreateProvidedFileSystem)), | 43 file_system_factory_(base::Bind(&CreateProvidedFileSystem)), |
| 44 registry_(new Registry(profile)), | |
| 59 weak_ptr_factory_(this) { | 45 weak_ptr_factory_(this) { |
| 60 extension_registry_->AddObserver(this); | 46 extension_registry_->AddObserver(this); |
| 61 } | 47 } |
| 62 | 48 |
| 63 Service::~Service() { | 49 Service::~Service() { |
| 64 extension_registry_->RemoveObserver(this); | 50 extension_registry_->RemoveObserver(this); |
| 65 | 51 |
| 66 // Provided file systems should be already unmounted because of receiving | 52 // Provided file systems should be already unmounted because of receiving |
| 67 // OnExtensionUnload calls for each installed extension. However, for tests | 53 // OnExtensionUnload calls for each installed extension. However, for tests |
| 68 // we may still have mounted extensions. | 54 // we may still have mounted extensions. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 97 DCHECK(observer); | 83 DCHECK(observer); |
| 98 observers_.RemoveObserver(observer); | 84 observers_.RemoveObserver(observer); |
| 99 } | 85 } |
| 100 | 86 |
| 101 void Service::SetFileSystemFactoryForTesting( | 87 void Service::SetFileSystemFactoryForTesting( |
| 102 const FileSystemFactoryCallback& factory_callback) { | 88 const FileSystemFactoryCallback& factory_callback) { |
| 103 DCHECK(!factory_callback.is_null()); | 89 DCHECK(!factory_callback.is_null()); |
| 104 file_system_factory_ = factory_callback; | 90 file_system_factory_ = factory_callback; |
| 105 } | 91 } |
| 106 | 92 |
| 93 void Service::SetRegistryForTesting(scoped_ptr<RegistryInterface> registry) { | |
| 94 DCHECK(registry); | |
| 95 registry_.reset(registry.release()); | |
| 96 } | |
| 97 | |
| 107 bool Service::MountFileSystem(const std::string& extension_id, | 98 bool Service::MountFileSystem(const std::string& extension_id, |
| 108 const MountOptions& options) { | 99 const MountOptions& options) { |
| 109 DCHECK(thread_checker_.CalledOnValidThread()); | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
| 110 | 101 |
| 111 // If already exists a file system provided by the same extension with this | 102 // If already exists a file system provided by the same extension with this |
| 112 // id, then abort. | 103 // id, then abort. |
| 113 if (GetProvidedFileSystem(extension_id, options.file_system_id)) { | 104 if (GetProvidedFileSystem(extension_id, options.file_system_id)) { |
| 114 FOR_EACH_OBSERVER(Observer, | 105 FOR_EACH_OBSERVER(Observer, |
| 115 observers_, | 106 observers_, |
| 116 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), | 107 OnProvidedFileSystemMount(ProvidedFileSystemInfo(), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 // mount_path = /provided/b33f1337-hello_world-5aa5 | 151 // mount_path = /provided/b33f1337-hello_world-5aa5 |
| 161 ProvidedFileSystemInfo file_system_info(extension_id, options, mount_path); | 152 ProvidedFileSystemInfo file_system_info(extension_id, options, mount_path); |
| 162 | 153 |
| 163 ProvidedFileSystemInterface* file_system = | 154 ProvidedFileSystemInterface* file_system = |
| 164 file_system_factory_.Run(profile_, file_system_info); | 155 file_system_factory_.Run(profile_, file_system_info); |
| 165 DCHECK(file_system); | 156 DCHECK(file_system); |
| 166 file_system_map_[FileSystemKey(extension_id, options.file_system_id)] = | 157 file_system_map_[FileSystemKey(extension_id, options.file_system_id)] = |
| 167 file_system; | 158 file_system; |
| 168 mount_point_name_to_key_map_[mount_point_name] = | 159 mount_point_name_to_key_map_[mount_point_name] = |
| 169 FileSystemKey(extension_id, options.file_system_id); | 160 FileSystemKey(extension_id, options.file_system_id); |
| 170 RememberFileSystem(file_system_info, *file_system->GetObservedEntries()); | 161 registry_->RememberFileSystem(file_system_info, |
| 162 *file_system->GetObservedEntries()); | |
| 171 | 163 |
| 172 FOR_EACH_OBSERVER( | 164 FOR_EACH_OBSERVER( |
| 173 Observer, | 165 Observer, |
| 174 observers_, | 166 observers_, |
| 175 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); | 167 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); |
| 176 | 168 |
| 177 return true; | 169 return true; |
| 178 } | 170 } |
| 179 | 171 |
| 180 bool Service::UnmountFileSystem(const std::string& extension_id, | 172 bool Service::UnmountFileSystem(const std::string& extension_id, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 213 } | 205 } |
| 214 | 206 |
| 215 FOR_EACH_OBSERVER( | 207 FOR_EACH_OBSERVER( |
| 216 Observer, | 208 Observer, |
| 217 observers_, | 209 observers_, |
| 218 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); | 210 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); |
| 219 | 211 |
| 220 mount_point_name_to_key_map_.erase(mount_point_name); | 212 mount_point_name_to_key_map_.erase(mount_point_name); |
| 221 | 213 |
| 222 if (reason == UNMOUNT_REASON_USER) { | 214 if (reason == UNMOUNT_REASON_USER) { |
| 223 ForgetFileSystem(file_system_info.extension_id(), | 215 registry_->ForgetFileSystem(file_system_info.extension_id(), |
| 224 file_system_info.file_system_id()); | 216 file_system_info.file_system_id()); |
| 225 } | 217 } |
| 226 | 218 |
| 227 delete file_system_it->second; | 219 delete file_system_it->second; |
| 228 file_system_map_.erase(file_system_it); | 220 file_system_map_.erase(file_system_it); |
| 229 | 221 |
| 230 return true; | 222 return true; |
| 231 } | 223 } |
| 232 | 224 |
| 233 bool Service::RequestUnmount(const std::string& extension_id, | 225 bool Service::RequestUnmount(const std::string& extension_id, |
| 234 const std::string& file_system_id) { | 226 const std::string& file_system_id) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN | 282 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN |
| 291 ? UNMOUNT_REASON_SHUTDOWN | 283 ? UNMOUNT_REASON_SHUTDOWN |
| 292 : UNMOUNT_REASON_USER); | 284 : UNMOUNT_REASON_USER); |
| 293 DCHECK(unmount_result); | 285 DCHECK(unmount_result); |
| 294 } | 286 } |
| 295 } | 287 } |
| 296 } | 288 } |
| 297 | 289 |
| 298 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, | 290 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, |
| 299 const extensions::Extension* extension) { | 291 const extensions::Extension* extension) { |
| 300 RestoreFileSystems(extension->id()); | 292 scoped_ptr<RegistryInterface::RestoredFileSystems> restored_file_systems = |
| 293 registry_->RestoreFileSystems(extension->id()); | |
| 294 | |
| 295 for (RegistryInterface::RestoredFileSystems::const_iterator it = | |
|
fukino
2014/10/20 09:42:04
According to http://chromium-cpp.appspot.com/ we m
mtomasz
2014/10/21 02:22:20
Good point! Done. For consistency I'll update the
| |
| 296 restored_file_systems->begin(); | |
| 297 it != restored_file_systems->end(); | |
| 298 ++it) { | |
| 299 const bool result = MountFileSystem(it->extension_id, it->options); | |
| 300 if (!result) { | |
| 301 LOG(ERROR) << "Failed to restore a provided file system from " | |
| 302 << "registry: " << it->extension_id << ", " | |
| 303 << it->options.file_system_id << ", " | |
| 304 << it->options.display_name << "."; | |
| 305 // Since remounting of the file system failed, then remove it from | |
| 306 // preferences to avoid remounting it over and over again with a failure. | |
| 307 registry_->ForgetFileSystem(it->extension_id, it->options.file_system_id); | |
| 308 continue; | |
| 309 } | |
| 310 | |
| 311 ProvidedFileSystemInterface* const file_system = | |
| 312 GetProvidedFileSystem(it->extension_id, it->options.file_system_id); | |
| 313 DCHECK(file_system); | |
| 314 file_system->GetObservedEntries()->insert(it->observed_entries.begin(), | |
| 315 it->observed_entries.end()); | |
| 316 } | |
| 301 } | 317 } |
| 302 | 318 |
| 303 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( | 319 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( |
| 304 const std::string& mount_point_name) { | 320 const std::string& mount_point_name) { |
| 305 DCHECK(thread_checker_.CalledOnValidThread()); | 321 DCHECK(thread_checker_.CalledOnValidThread()); |
| 306 | 322 |
| 307 const MountPointNameToKeyMap::const_iterator mapping_it = | 323 const MountPointNameToKeyMap::const_iterator mapping_it = |
| 308 mount_point_name_to_key_map_.find(mount_point_name); | 324 mount_point_name_to_key_map_.find(mount_point_name); |
| 309 if (mapping_it == mount_point_name_to_key_map_.end()) | 325 if (mapping_it == mount_point_name_to_key_map_.end()) |
| 310 return NULL; | 326 return NULL; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 325 // invoked, and observers notified, so there is no need to call them now. | 341 // invoked, and observers notified, so there is no need to call them now. |
| 326 if (error != base::File::FILE_OK) { | 342 if (error != base::File::FILE_OK) { |
| 327 FOR_EACH_OBSERVER(Observer, | 343 FOR_EACH_OBSERVER(Observer, |
| 328 observers_, | 344 observers_, |
| 329 OnProvidedFileSystemUnmount(file_system_info, error)); | 345 OnProvidedFileSystemUnmount(file_system_info, error)); |
| 330 } | 346 } |
| 331 } | 347 } |
| 332 | 348 |
| 333 void Service::OnObservedEntryChanged( | 349 void Service::OnObservedEntryChanged( |
| 334 const ProvidedFileSystemInfo& file_system_info, | 350 const ProvidedFileSystemInfo& file_system_info, |
| 335 const base::FilePath& observed_path, | 351 const ObservedEntry& observed_entry, |
| 336 ChangeType change_type, | 352 ChangeType change_type, |
| 337 const ChildChanges& child_changes, | 353 const ChildChanges& child_changes, |
| 338 const base::Closure& callback) { | 354 const base::Closure& callback) { |
| 339 callback.Run(); | 355 callback.Run(); |
| 340 } | 356 } |
| 341 | 357 |
| 342 void Service::OnObservedEntryTagUpdated( | 358 void Service::OnObservedEntryTagUpdated( |
| 343 const ProvidedFileSystemInfo& file_system_info, | 359 const ProvidedFileSystemInfo& file_system_info, |
| 344 const base::FilePath& observed_path, | 360 const ObservedEntry& observed_entry) { |
| 345 const std::string& tag) { | |
| 346 PrefService* const pref_service = profile_->GetPrefs(); | 361 PrefService* const pref_service = profile_->GetPrefs(); |
| 347 DCHECK(pref_service); | 362 DCHECK(pref_service); |
| 348 | 363 |
| 349 // TODO(mtomasz): Consider optimizing it by moving information about observed | 364 registry_->UpdateObservedEntryTag(file_system_info, observed_entry); |
| 350 // entries, or even file systems to leveldb. | |
| 351 DictionaryPrefUpdate dict_update(pref_service, | |
| 352 prefs::kFileSystemProviderMounted); | |
| 353 | |
| 354 // All of the following checks should not happen in healthy environment. | |
| 355 // However, since they rely on storage, DCHECKs can't be used. | |
| 356 base::DictionaryValue* file_systems_per_extension = NULL; | |
| 357 base::DictionaryValue* file_system = NULL; | |
| 358 base::DictionaryValue* observed_entries = NULL; | |
| 359 base::DictionaryValue* observed_entry = NULL; | |
| 360 if (!dict_update->GetDictionaryWithoutPathExpansion( | |
| 361 file_system_info.extension_id(), &file_systems_per_extension) || | |
| 362 !file_systems_per_extension->GetDictionaryWithoutPathExpansion( | |
| 363 file_system_info.file_system_id(), &file_system) || | |
| 364 !file_system->GetDictionaryWithoutPathExpansion(kPrefKeyObservedEntries, | |
| 365 &observed_entries) || | |
| 366 !observed_entries->GetDictionaryWithoutPathExpansion( | |
| 367 observed_path.value(), &observed_entry)) { | |
| 368 // Broken preferences. | |
| 369 LOG(ERROR) << "Broken preferences detected while updating a tag."; | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 observed_entry->SetStringWithoutPathExpansion(kPrefKeyObservedEntryLastTag, | |
| 374 tag); | |
| 375 } | 365 } |
| 376 | 366 |
| 377 void Service::OnObservedEntryListChanged( | 367 void Service::OnObservedEntryListChanged( |
| 378 const ProvidedFileSystemInfo& file_system_info, | 368 const ProvidedFileSystemInfo& file_system_info, |
| 379 const ObservedEntries& observed_entries) { | 369 const ObservedEntries& observed_entries) { |
| 380 RememberFileSystem(file_system_info, observed_entries); | 370 registry_->RememberFileSystem(file_system_info, observed_entries); |
| 381 } | |
| 382 | |
| 383 void Service::RememberFileSystem(const ProvidedFileSystemInfo& file_system_info, | |
| 384 const ObservedEntries& observed_entries) { | |
| 385 base::DictionaryValue* const file_system = new base::DictionaryValue(); | |
| 386 file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId, | |
| 387 file_system_info.file_system_id()); | |
| 388 file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName, | |
| 389 file_system_info.display_name()); | |
| 390 file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable, | |
| 391 file_system_info.writable()); | |
| 392 file_system->SetBooleanWithoutPathExpansion( | |
| 393 kPrefKeySupportsNotifyTag, file_system_info.supports_notify_tag()); | |
| 394 | |
| 395 base::DictionaryValue* const observed_entries_value = | |
| 396 new base::DictionaryValue(); | |
| 397 file_system->SetWithoutPathExpansion(kPrefKeyObservedEntries, | |
| 398 observed_entries_value); | |
| 399 | |
| 400 for (ObservedEntries::const_iterator it = observed_entries.begin(); | |
| 401 it != observed_entries.end(); | |
| 402 ++it) { | |
| 403 base::DictionaryValue* const observed_entry = new base::DictionaryValue(); | |
| 404 observed_entries_value->SetWithoutPathExpansion(it->first.value(), | |
| 405 observed_entry); | |
| 406 observed_entry->SetStringWithoutPathExpansion( | |
| 407 kPrefKeyObservedEntryEntryPath, it->second.entry_path.value()); | |
| 408 observed_entry->SetBooleanWithoutPathExpansion( | |
| 409 kPrefKeyObservedEntryRecursive, it->second.recursive); | |
| 410 observed_entry->SetStringWithoutPathExpansion(kPrefKeyObservedEntryLastTag, | |
| 411 it->second.last_tag); | |
| 412 } | |
| 413 | |
| 414 PrefService* const pref_service = profile_->GetPrefs(); | |
| 415 DCHECK(pref_service); | |
| 416 | |
| 417 DictionaryPrefUpdate dict_update(pref_service, | |
| 418 prefs::kFileSystemProviderMounted); | |
| 419 | |
| 420 base::DictionaryValue* file_systems_per_extension = NULL; | |
| 421 if (!dict_update->GetDictionaryWithoutPathExpansion( | |
| 422 file_system_info.extension_id(), &file_systems_per_extension)) { | |
| 423 file_systems_per_extension = new base::DictionaryValue(); | |
| 424 dict_update->SetWithoutPathExpansion(file_system_info.extension_id(), | |
| 425 file_systems_per_extension); | |
| 426 } | |
| 427 | |
| 428 file_systems_per_extension->SetWithoutPathExpansion( | |
| 429 file_system_info.file_system_id(), file_system); | |
| 430 } | |
| 431 | |
| 432 void Service::ForgetFileSystem(const std::string& extension_id, | |
| 433 const std::string& file_system_id) { | |
| 434 PrefService* const pref_service = profile_->GetPrefs(); | |
| 435 DCHECK(pref_service); | |
| 436 | |
| 437 DictionaryPrefUpdate dict_update(pref_service, | |
| 438 prefs::kFileSystemProviderMounted); | |
| 439 | |
| 440 base::DictionaryValue* file_systems_per_extension = NULL; | |
| 441 if (!dict_update->GetDictionaryWithoutPathExpansion( | |
| 442 extension_id, &file_systems_per_extension)) | |
| 443 return; // Nothing to forget. | |
| 444 | |
| 445 file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL); | |
| 446 if (!file_systems_per_extension->size()) | |
| 447 dict_update->Remove(extension_id, NULL); | |
| 448 } | |
| 449 | |
| 450 void Service::RestoreFileSystems(const std::string& extension_id) { | |
| 451 // TODO(mtomasz): Restore observed entries together with their tags. | |
| 452 PrefService* const pref_service = profile_->GetPrefs(); | |
| 453 DCHECK(pref_service); | |
| 454 | |
| 455 const base::DictionaryValue* const file_systems = | |
| 456 pref_service->GetDictionary(prefs::kFileSystemProviderMounted); | |
| 457 DCHECK(file_systems); | |
| 458 | |
| 459 const base::DictionaryValue* file_systems_per_extension = NULL; | |
| 460 if (!file_systems->GetDictionaryWithoutPathExpansion( | |
| 461 extension_id, &file_systems_per_extension)) { | |
| 462 return; // Nothing to restore. | |
| 463 } | |
| 464 | |
| 465 // Use a copy of the dictionary, since the original one may be modified while | |
| 466 // iterating over it. | |
| 467 scoped_ptr<const base::DictionaryValue> file_systems_per_extension_copy( | |
| 468 file_systems_per_extension->DeepCopy()); | |
| 469 | |
| 470 for (base::DictionaryValue::Iterator it(*file_systems_per_extension_copy); | |
| 471 !it.IsAtEnd(); | |
| 472 it.Advance()) { | |
| 473 const base::Value* file_system_value = NULL; | |
| 474 const base::DictionaryValue* file_system = NULL; | |
| 475 file_systems_per_extension_copy->GetWithoutPathExpansion( | |
| 476 it.key(), &file_system_value); | |
| 477 DCHECK(file_system_value); | |
| 478 | |
| 479 std::string file_system_id; | |
| 480 std::string display_name; | |
| 481 bool writable = false; | |
| 482 bool supports_notify_tag = false; | |
| 483 | |
| 484 if (!file_system_value->GetAsDictionary(&file_system) || | |
| 485 !file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId, | |
| 486 &file_system_id) || | |
| 487 !file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName, | |
| 488 &display_name) || | |
| 489 !file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable, | |
| 490 &writable) || | |
| 491 !file_system->GetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag, | |
| 492 &supports_notify_tag) || | |
| 493 file_system_id.empty() || display_name.empty()) { | |
| 494 LOG(ERROR) | |
| 495 << "Malformed provided file system information in preferences."; | |
| 496 continue; | |
| 497 } | |
| 498 | |
| 499 MountOptions options; | |
| 500 options.file_system_id = file_system_id; | |
| 501 options.display_name = display_name; | |
| 502 options.writable = writable; | |
| 503 options.supports_notify_tag = supports_notify_tag; | |
| 504 | |
| 505 const bool result = MountFileSystem(extension_id, options); | |
| 506 if (!result) { | |
| 507 LOG(ERROR) << "Failed to restore a provided file system from " | |
| 508 << "preferences: " << extension_id << ", " << file_system_id | |
| 509 << ", " << display_name << "."; | |
| 510 // Since remounting of the file system failed, then remove it from | |
| 511 // preferences to avoid remounting it over and over again with a failure. | |
| 512 ForgetFileSystem(extension_id, file_system_id); | |
| 513 } | |
| 514 | |
| 515 // Restore observed entries. It's optional, since this field is new. | |
| 516 const base::DictionaryValue* observed_entries = NULL; | |
| 517 if (file_system->GetDictionaryWithoutPathExpansion(kPrefKeyObservedEntries, | |
| 518 &observed_entries)) { | |
| 519 ProvidedFileSystemInterface* const restored_file_system = | |
| 520 GetProvidedFileSystem(extension_id, file_system_id); | |
| 521 DCHECK(restored_file_system); | |
| 522 | |
| 523 for (base::DictionaryValue::Iterator it(*observed_entries); !it.IsAtEnd(); | |
| 524 it.Advance()) { | |
| 525 const base::Value* observed_entry_value = NULL; | |
| 526 const base::DictionaryValue* observed_entry = NULL; | |
| 527 observed_entries->GetWithoutPathExpansion(it.key(), | |
| 528 &observed_entry_value); | |
| 529 DCHECK(observed_entry_value); | |
| 530 | |
| 531 std::string entry_path; | |
| 532 bool recursive = false; | |
| 533 std::string last_tag; | |
| 534 | |
| 535 if (!observed_entry_value->GetAsDictionary(&observed_entry) || | |
| 536 !observed_entry->GetStringWithoutPathExpansion( | |
| 537 kPrefKeyObservedEntryEntryPath, &entry_path) || | |
| 538 !observed_entry->GetBooleanWithoutPathExpansion( | |
| 539 kPrefKeyObservedEntryRecursive, &recursive) || | |
| 540 !observed_entry->GetStringWithoutPathExpansion( | |
| 541 kPrefKeyObservedEntryLastTag, &last_tag) || | |
| 542 it.key() != entry_path || entry_path.empty() || | |
| 543 (!options.supports_notify_tag && !last_tag.empty())) { | |
| 544 LOG(ERROR) << "Malformed observed entry information in preferences."; | |
| 545 continue; | |
| 546 } | |
| 547 | |
| 548 ObservedEntry restored_observed_entry; | |
| 549 restored_observed_entry.entry_path = | |
| 550 base::FilePath::FromUTF8Unsafe(entry_path); | |
| 551 restored_observed_entry.recursive = recursive; | |
| 552 restored_observed_entry.last_tag = last_tag; | |
| 553 (*restored_file_system | |
| 554 ->GetObservedEntries())[restored_observed_entry.entry_path] = | |
| 555 restored_observed_entry; | |
| 556 } | |
| 557 } | |
| 558 } | |
| 559 } | 371 } |
| 560 | 372 |
| 561 } // namespace file_system_provider | 373 } // namespace file_system_provider |
| 562 } // namespace chromeos | 374 } // namespace chromeos |
| OLD | NEW |