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 |