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

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

Issue 661393002: [fsp] Separate logic for saving/restoring state to a separate class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: C++11 features. Created 6 years, 2 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
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
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
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
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
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 (const auto& restored_file_system : *restored_file_systems) {
296 const bool result = MountFileSystem(restored_file_system.extension_id,
297 restored_file_system.options);
298 if (!result) {
299 LOG(ERROR) << "Failed to restore a provided file system from "
300 << "registry: " << restored_file_system.extension_id << ", "
301 << restored_file_system.options.file_system_id << ", "
302 << restored_file_system.options.display_name << ".";
303 // Since remounting of the file system failed, then remove it from
304 // preferences to avoid remounting it over and over again with a failure.
305 registry_->ForgetFileSystem(restored_file_system.extension_id,
306 restored_file_system.options.file_system_id);
307 continue;
308 }
309
310 ProvidedFileSystemInterface* const file_system =
311 GetProvidedFileSystem(restored_file_system.extension_id,
312 restored_file_system.options.file_system_id);
313 DCHECK(file_system);
314 file_system->GetObservedEntries()->insert(
315 restored_file_system.observed_entries.begin(),
316 restored_file_system.observed_entries.end());
317 }
301 } 318 }
302 319
303 ProvidedFileSystemInterface* Service::GetProvidedFileSystem( 320 ProvidedFileSystemInterface* Service::GetProvidedFileSystem(
304 const std::string& mount_point_name) { 321 const std::string& mount_point_name) {
305 DCHECK(thread_checker_.CalledOnValidThread()); 322 DCHECK(thread_checker_.CalledOnValidThread());
306 323
307 const MountPointNameToKeyMap::const_iterator mapping_it = 324 const MountPointNameToKeyMap::const_iterator mapping_it =
308 mount_point_name_to_key_map_.find(mount_point_name); 325 mount_point_name_to_key_map_.find(mount_point_name);
309 if (mapping_it == mount_point_name_to_key_map_.end()) 326 if (mapping_it == mount_point_name_to_key_map_.end())
310 return NULL; 327 return NULL;
(...skipping 14 matching lines...) Expand all
325 // invoked, and observers notified, so there is no need to call them now. 342 // invoked, and observers notified, so there is no need to call them now.
326 if (error != base::File::FILE_OK) { 343 if (error != base::File::FILE_OK) {
327 FOR_EACH_OBSERVER(Observer, 344 FOR_EACH_OBSERVER(Observer,
328 observers_, 345 observers_,
329 OnProvidedFileSystemUnmount(file_system_info, error)); 346 OnProvidedFileSystemUnmount(file_system_info, error));
330 } 347 }
331 } 348 }
332 349
333 void Service::OnObservedEntryChanged( 350 void Service::OnObservedEntryChanged(
334 const ProvidedFileSystemInfo& file_system_info, 351 const ProvidedFileSystemInfo& file_system_info,
335 const base::FilePath& observed_path, 352 const ObservedEntry& observed_entry,
336 ChangeType change_type, 353 ChangeType change_type,
337 const ChildChanges& child_changes, 354 const ChildChanges& child_changes,
338 const base::Closure& callback) { 355 const base::Closure& callback) {
339 callback.Run(); 356 callback.Run();
340 } 357 }
341 358
342 void Service::OnObservedEntryTagUpdated( 359 void Service::OnObservedEntryTagUpdated(
343 const ProvidedFileSystemInfo& file_system_info, 360 const ProvidedFileSystemInfo& file_system_info,
344 const base::FilePath& observed_path, 361 const ObservedEntry& observed_entry) {
345 const std::string& tag) {
346 PrefService* const pref_service = profile_->GetPrefs(); 362 PrefService* const pref_service = profile_->GetPrefs();
347 DCHECK(pref_service); 363 DCHECK(pref_service);
348 364
349 // TODO(mtomasz): Consider optimizing it by moving information about observed 365 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 } 366 }
376 367
377 void Service::OnObservedEntryListChanged( 368 void Service::OnObservedEntryListChanged(
378 const ProvidedFileSystemInfo& file_system_info, 369 const ProvidedFileSystemInfo& file_system_info,
379 const ObservedEntries& observed_entries) { 370 const ObservedEntries& observed_entries) {
380 RememberFileSystem(file_system_info, observed_entries); 371 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 } 372 }
560 373
561 } // namespace file_system_provider 374 } // namespace file_system_provider
562 } // namespace chromeos 375 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698