service.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose// Copyright 2014 The Chromium Authors. All rights reserved.
2740d490593e0de8732a697c9f77b90ddd463863bJordan Rose// Use of this source code is governed by a BSD-style license that can be
3740d490593e0de8732a697c9f77b90ddd463863bJordan Rose// found in the LICENSE file.
4740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
5740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/service.h"
6740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
7740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "base/files/file_path.h"
8740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "base/prefs/pref_service.h"
9740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "base/prefs/scoped_user_pref_update.h"
10740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "base/stl_util.h"
11740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
12740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/observer.h"
13740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
14740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
15740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
16740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
17740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "chrome/common/pref_names.h"
18740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "components/pref_registry/pref_registry_syncable.h"
19740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "extensions/browser/extension_registry.h"
20740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "extensions/browser/extension_system.h"
21740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "webkit/browser/fileapi/external_mount_points.h"
22a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
2330a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruthnamespace chromeos {
24de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rosenamespace file_system_provider {
25740d490593e0de8732a697c9f77b90ddd463863bJordan Rosenamespace {
26b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose
27740d490593e0de8732a697c9f77b90ddd463863bJordan Rose// Maximum number of file systems to be mounted in the same time, per profile.
28740d490593e0de8732a697c9f77b90ddd463863bJordan Roseconst size_t kMaxFileSystems = 16;
2928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
3028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose// Default factory for provided file systems. |profile| must not be NULL.
3128038f33aa2db4833881fea757a1f0daf85ac02bJordan RoseProvidedFileSystemInterface* CreateProvidedFileSystem(
32740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    Profile* profile,
33740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    const ProvidedFileSystemInfo& file_system_info) {
34740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(profile);
35740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  return new ProvidedFileSystem(profile, file_system_info);
36740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}
37740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
38740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}  // namespace
39645baeed6800f952e9ad1d5666e01080385531a2Jordan Rose
40645baeed6800f952e9ad1d5666e01080385531a2Jordan Roseconst char kPrefKeyFileSystemId[] = "file-system-id";
418d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Roseconst char kPrefKeyDisplayName[] = "display-name";
42645baeed6800f952e9ad1d5666e01080385531a2Jordan Roseconst char kPrefKeyWritable[] = "writable";
43645baeed6800f952e9ad1d5666e01080385531a2Jordan Rose
44645baeed6800f952e9ad1d5666e01080385531a2Jordan Rosevoid RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
4570cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose  registry->RegisterDictionaryPref(
46740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      prefs::kFileSystemProviderMounted,
4770cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
488919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose}
49740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
50740d490593e0de8732a697c9f77b90ddd463863bJordan RoseService::Service(Profile* profile,
51972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                 extensions::ExtensionRegistry* extension_registry)
52d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose    : profile_(profile),
53972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose      extension_registry_(extension_registry),
54d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      file_system_factory_(base::Bind(CreateProvidedFileSystem)),
55d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      weak_ptr_factory_(this) {
56d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose  extension_registry_->AddObserver(this);
57d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose}
58d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose
59d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan RoseService::~Service() {
60d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose  extension_registry_->RemoveObserver(this);
61d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose
62d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose  // Provided file systems should be already unmounted because of receiving
6357c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose  // OnExtensionUnload calls for each installed extension. However, for tests
6457c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose  // we may still have mounted extensions.
6557c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose  // TODO(mtomasz): Create a TestingService class and remove this code.
6657c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose  ProvidedFileSystemMap::iterator it = file_system_map_.begin();
6757c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose  while (it != file_system_map_.end()) {
6857c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose    const std::string file_system_id =
6957c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose        it->second->GetFileSystemInfo().file_system_id();
70d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose    const std::string extension_id =
71b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose        it->second->GetFileSystemInfo().extension_id();
721becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks    ++it;
735960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks    const bool unmount_result = UnmountFileSystem(
741becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks        extension_id, file_system_id, UNMOUNT_REASON_SHUTDOWN);
751becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks    DCHECK(unmount_result);
761becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks  }
771becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks
781becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks  DCHECK_EQ(0u, file_system_map_.size());
79fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks  STLDeleteValues(&file_system_map_);
801becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks}
811becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks
82fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks// static
835960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna ZaksService* Service::Get(content::BrowserContext* context) {
845960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks  return ServiceFactory::Get(context);
855960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks}
861becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks
871becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaksvoid Service::AddObserver(Observer* observer) {
88fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks  DCHECK(observer);
895960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks  observers_.AddObserver(observer);
90fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks}
91fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks
92fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaksvoid Service::RemoveObserver(Observer* observer) {
93fc05decf08feefd2ffe8cc250219aee6eab3119cAnna Zaks  DCHECK(observer);
945960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks  observers_.RemoveObserver(observer);
951becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks}
961becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks
971becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaksvoid Service::SetFileSystemFactoryForTesting(
981becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks    const FileSystemFactoryCallback& factory_callback) {
995960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks  DCHECK(!factory_callback.is_null());
1001becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks  file_system_factory_ = factory_callback;
1011becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks}
1021becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaks
1031becab2120142b1be87d684a68d3bea98f5abfb5Anna Zaksbool Service::MountFileSystem(const std::string& extension_id,
104e90d3f847dcce76237078b67db8895eb7a24189eAnna Zaks                              const std::string& file_system_id,
105e90d3f847dcce76237078b67db8895eb7a24189eAnna Zaks                              const std::string& display_name,
106740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                              bool writable) {
107740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
108972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose
109972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // If already exists a file system provided by the same extension with this
110972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // id, then abort.
111972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  if (GetProvidedFileSystem(extension_id, file_system_id)) {
112972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose    FOR_EACH_OBSERVER(Observer,
113972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                      observers_,
114972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                      OnProvidedFileSystemMount(ProvidedFileSystemInfo(),
115740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                                                base::File::FILE_ERROR_EXISTS));
116740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return false;
117740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  }
118740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
119b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  // Restrict number of file systems to prevent system abusing.
1207c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  if (file_system_map_.size() + 1 > kMaxFileSystems) {
1217c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose    FOR_EACH_OBSERVER(
122b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose        Observer,
123b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose        observers_,
124f56faa01936b9cf909623d7f06e3c2569ca4a78eDmitri Gribenko        OnProvidedFileSystemMount(ProvidedFileSystemInfo(),
1257c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose                                  base::File::FILE_ERROR_TOO_MANY_OPENED));
126740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return false;
127b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  }
128b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose
129972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  fileapi::ExternalMountPoints* const mount_points =
130972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose      fileapi::ExternalMountPoints::GetSystemInstance();
131972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  DCHECK(mount_points);
132972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose
133b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  // The mount point path and name are unique per system, since they are system
134b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  // wide. This is necessary for copying between profiles.
135972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  const base::FilePath& mount_path =
136972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose      util::GetMountPath(profile_, extension_id, file_system_id);
137972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe();
138972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose
139972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  if (!mount_points->RegisterFileSystem(mount_point_name,
140972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                                        fileapi::kFileSystemTypeProvided,
141972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                                        fileapi::FileSystemMountOption(),
142972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                                        mount_path)) {
143d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose    FOR_EACH_OBSERVER(
144d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose        Observer,
1455204d9e2fe0ea4e4b9c85087e355021c93221764Jordan Rose        observers_,
146972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose        OnProvidedFileSystemMount(ProvidedFileSystemInfo(),
147b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose                                  base::File::FILE_ERROR_INVALID_OPERATION));
1485204d9e2fe0ea4e4b9c85087e355021c93221764Jordan Rose    return false;
149972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  }
150972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose
151972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // Store the file system descriptor. Use the mount point name as the file
152972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // system provider file system id.
153972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // Examples:
154972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  //   file_system_id = hello_world
155b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  //   mount_point_name =  b33f1337-hello_world-5aa5
156972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  //   writable = false
157972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  //   mount_path = /provided/b33f1337-hello_world-5aa5
158972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  ProvidedFileSystemInfo file_system_info(
159740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      extension_id, file_system_id, display_name, writable, mount_path);
160740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
161b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  ProvidedFileSystemInterface* file_system =
162740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      file_system_factory_.Run(profile_, file_system_info);
163740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(file_system);
164972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system;
165740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  mount_point_name_to_key_map_[mount_point_name] =
166740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      FileSystemKey(extension_id, file_system_id);
167740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  RememberFileSystem(file_system_info);
168740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
1697c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  FOR_EACH_OBSERVER(
170740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      Observer,
171740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      observers_,
1727c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose      OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK));
1737c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
174b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  return true;
1757c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose}
176b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose
177740d490593e0de8732a697c9f77b90ddd463863bJordan Rosebool Service::UnmountFileSystem(const std::string& extension_id,
178740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                                const std::string& file_system_id,
1797c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose                                UnmountReason reason) {
1807c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
1817c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
182740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  const ProvidedFileSystemMap::iterator file_system_it =
1835a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks      file_system_map_.find(FileSystemKey(extension_id, file_system_id));
1840a6e09f67c719c318856be19d57e19972101f62cJordan Rose  if (file_system_it == file_system_map_.end()) {
1855a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks    const ProvidedFileSystemInfo empty_file_system_info;
1865a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks    FOR_EACH_OBSERVER(
1875a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks        Observer,
1885a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks        observers_,
1895a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks        OnProvidedFileSystemUnmount(empty_file_system_info,
1905a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks                                    base::File::FILE_ERROR_NOT_FOUND));
1915a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks    return false;
1925a90193ad825656d4a03099cd5e9c928d1782b5eAnna Zaks  }
193ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose
1945960f4aeac9760198c80e05d70d8dadb1db0ff0eAnna Zaks  fileapi::ExternalMountPoints* const mount_points =
195ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek      fileapi::ExternalMountPoints::GetSystemInstance();
196ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose  DCHECK(mount_points);
197740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
198740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  const ProvidedFileSystemInfo& file_system_info =
199b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose      file_system_it->second->GetFileSystemInfo();
200b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose
201b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  const std::string mount_point_name =
202740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      file_system_info.mount_path().BaseName().value();
203740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  if (!mount_points->RevokeFileSystem(mount_point_name)) {
204740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    FOR_EACH_OBSERVER(
205740d490593e0de8732a697c9f77b90ddd463863bJordan Rose        Observer,
206740d490593e0de8732a697c9f77b90ddd463863bJordan Rose        observers_,
207740d490593e0de8732a697c9f77b90ddd463863bJordan Rose        OnProvidedFileSystemUnmount(file_system_info,
2087c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose                                    base::File::FILE_ERROR_INVALID_OPERATION));
209740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return false;
210740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  }
211740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
212740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  FOR_EACH_OBSERVER(
213740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      Observer,
214740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      observers_,
215740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
216740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
217740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  mount_point_name_to_key_map_.erase(mount_point_name);
218740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
219b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  if (reason == UNMOUNT_REASON_USER) {
220740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    ForgetFileSystem(file_system_info.extension_id(),
221740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                     file_system_info.file_system_id());
222740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  }
223740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
224740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  delete file_system_it->second;
225740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  file_system_map_.erase(file_system_it);
226740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
227740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  return true;
228740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}
229740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
230740d490593e0de8732a697c9f77b90ddd463863bJordan Rosebool Service::RequestUnmount(const std::string& extension_id,
231de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose                             const std::string& file_system_id) {
232de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
2337c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
2347c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  ProvidedFileSystemMap::iterator file_system_it =
2357c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose      file_system_map_.find(FileSystemKey(extension_id, file_system_id));
236de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose  if (file_system_it == file_system_map_.end())
237740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return false;
2387c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
239740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  file_system_it->second->RequestUnmount(
240740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      base::Bind(&Service::OnRequestUnmountStatus,
241740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                 weak_ptr_factory_.GetWeakPtr(),
2427c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose                 file_system_it->second->GetFileSystemInfo()));
243740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  return true;
244740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}
2457c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
246740d490593e0de8732a697c9f77b90ddd463863bJordan Rosestd::vector<ProvidedFileSystemInfo> Service::GetProvidedFileSystemInfoList() {
2477c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
248740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
249740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  std::vector<ProvidedFileSystemInfo> result;
250740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  for (ProvidedFileSystemMap::const_iterator it = file_system_map_.begin();
251740d490593e0de8732a697c9f77b90ddd463863bJordan Rose       it != file_system_map_.end();
2522f3017f9cbd3774f690c979410bfec38423d03afJordan Rose       ++it) {
2532f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    result.push_back(it->second->GetFileSystemInfo());
2542f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  }
2552f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  return result;
2562f3017f9cbd3774f690c979410bfec38423d03afJordan Rose}
2572f3017f9cbd3774f690c979410bfec38423d03afJordan Rose
258740d490593e0de8732a697c9f77b90ddd463863bJordan RoseProvidedFileSystemInterface* Service::GetProvidedFileSystem(
259740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    const std::string& extension_id,
260740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    const std::string& file_system_id) {
26185d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
26285d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose
26385d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose  const ProvidedFileSystemMap::const_iterator file_system_it =
26485d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose      file_system_map_.find(FileSystemKey(extension_id, file_system_id));
26585d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose  if (file_system_it == file_system_map_.end())
2667c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose    return NULL;
2677c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
2687c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  return file_system_it->second;
26985d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose}
2702f3017f9cbd3774f690c979410bfec38423d03afJordan Rose
2712f3017f9cbd3774f690c979410bfec38423d03afJordan Rosevoid Service::OnExtensionUnloaded(
2722f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    content::BrowserContext* browser_context,
2732f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    const extensions::Extension* extension,
2742f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    extensions::UnloadedExtensionInfo::Reason reason) {
2752f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  // Unmount all of the provided file systems associated with this extension.
2762f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  ProvidedFileSystemMap::iterator it = file_system_map_.begin();
2772f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  while (it != file_system_map_.end()) {
2782f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    const ProvidedFileSystemInfo& file_system_info =
2792f3017f9cbd3774f690c979410bfec38423d03afJordan Rose        it->second->GetFileSystemInfo();
2802f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    // Advance the iterator beforehand, otherwise it will become invalidated
2812f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    // by the UnmountFileSystem() call.
2822f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    ++it;
2832f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    if (file_system_info.extension_id() == extension->id()) {
2842f3017f9cbd3774f690c979410bfec38423d03afJordan Rose      const bool unmount_result = UnmountFileSystem(
2852f3017f9cbd3774f690c979410bfec38423d03afJordan Rose          file_system_info.extension_id(),
2862f3017f9cbd3774f690c979410bfec38423d03afJordan Rose          file_system_info.file_system_id(),
2872f3017f9cbd3774f690c979410bfec38423d03afJordan Rose          reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN
2882f3017f9cbd3774f690c979410bfec38423d03afJordan Rose              ? UNMOUNT_REASON_SHUTDOWN
2892f3017f9cbd3774f690c979410bfec38423d03afJordan Rose              : UNMOUNT_REASON_USER);
2902f3017f9cbd3774f690c979410bfec38423d03afJordan Rose      DCHECK(unmount_result);
2912f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    }
2922f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  }
2932f3017f9cbd3774f690c979410bfec38423d03afJordan Rose}
2942f3017f9cbd3774f690c979410bfec38423d03afJordan Rose
2952f3017f9cbd3774f690c979410bfec38423d03afJordan Rosevoid Service::OnExtensionLoaded(content::BrowserContext* browser_context,
2962f3017f9cbd3774f690c979410bfec38423d03afJordan Rose                                const extensions::Extension* extension) {
2972f3017f9cbd3774f690c979410bfec38423d03afJordan Rose  RestoreFileSystems(extension->id());
2982f3017f9cbd3774f690c979410bfec38423d03afJordan Rose}
2992f3017f9cbd3774f690c979410bfec38423d03afJordan Rose
3002f3017f9cbd3774f690c979410bfec38423d03afJordan RoseProvidedFileSystemInterface* Service::GetProvidedFileSystem(
3012f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    const std::string& mount_point_name) {
30228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  DCHECK(thread_checker_.CalledOnValidThread());
3038d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose
30428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const MountPointNameToKeyMap::const_iterator mapping_it =
30528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      mount_point_name_to_key_map_.find(mount_point_name);
306740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  if (mapping_it == mount_point_name_to_key_map_.end())
307740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return NULL;
308740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
309740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  const ProvidedFileSystemMap::const_iterator file_system_it =
310740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      file_system_map_.find(mapping_it->second);
311740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  if (file_system_it == file_system_map_.end())
312740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return NULL;
313ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose
314ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose  return file_system_it->second;
315ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose}
316ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose
317ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rosevoid Service::OnRequestUnmountStatus(
318ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose    const ProvidedFileSystemInfo& file_system_info,
319ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose    base::File::Error error) {
320ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose  // Notify observers about failure in unmounting, since mount() will not be
321972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // called by the provided file system. In case of success mount() will be
322972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  // invoked, and observers notified, so there is no need to call them now.
323d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose  if (error != base::File::FILE_OK) {
324972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose    FOR_EACH_OBSERVER(Observer,
325972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose                      observers_,
326d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose                      OnProvidedFileSystemUnmount(file_system_info, error));
327972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose  }
328972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose}
329972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose
3306062334cc388bce69fb3978c4ecb26c6485a5c2bJordan Rosevoid Service::RememberFileSystem(
3316062334cc388bce69fb3978c4ecb26c6485a5c2bJordan Rose    const ProvidedFileSystemInfo& file_system_info) {
3326062334cc388bce69fb3978c4ecb26c6485a5c2bJordan Rose  base::DictionaryValue* file_system = new base::DictionaryValue();
33385d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose  file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId,
33416e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks                                             file_system_info.file_system_id());
33516e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks  file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName,
33616e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks                                             file_system_info.display_name());
337e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable,
338740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                                              file_system_info.writable());
339740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
340740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  PrefService* const pref_service = profile_->GetPrefs();
341740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(pref_service);
342e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose
343e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  DictionaryPrefUpdate dict_update(pref_service,
344e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose                                   prefs::kFileSystemProviderMounted);
345e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose
346e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  base::DictionaryValue* file_systems_per_extension = NULL;
347e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  if (!dict_update->GetDictionaryWithoutPathExpansion(
348e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose          file_system_info.extension_id(), &file_systems_per_extension)) {
349e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose    file_systems_per_extension = new base::DictionaryValue();
350e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose    dict_update->SetWithoutPathExpansion(file_system_info.extension_id(),
351e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose                                         file_systems_per_extension);
352e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  }
353e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose
354e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  file_systems_per_extension->SetWithoutPathExpansion(
355e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose      file_system_info.file_system_id(), file_system);
356e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose}
357e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose
358ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rosevoid Service::ForgetFileSystem(const std::string& extension_id,
359e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose                               const std::string& file_system_id) {
360ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose  PrefService* const pref_service = profile_->GetPrefs();
361e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  DCHECK(pref_service);
362740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
363740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DictionaryPrefUpdate dict_update(pref_service,
364740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                                   prefs::kFileSystemProviderMounted);
365e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose
366e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  base::DictionaryValue* file_systems_per_extension = NULL;
367e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose  if (!dict_update->GetDictionaryWithoutPathExpansion(
368e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose          extension_id, &file_systems_per_extension))
369e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose    return;  // Nothing to forget.
370740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
371740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL);
372740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  if (!file_systems_per_extension->size())
373740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    dict_update->Remove(extension_id, NULL);
374e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose}
375740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
376740d490593e0de8732a697c9f77b90ddd463863bJordan Rosevoid Service::RestoreFileSystems(const std::string& extension_id) {
377740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  PrefService* const pref_service = profile_->GetPrefs();
378740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(pref_service);
3790ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
380b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  const base::DictionaryValue* const file_systems =
38142c72c258e08ca79c9267346b4badcddd8fcd001Benjamin Kramer      pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
382740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  DCHECK(file_systems);
383740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
384b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  const base::DictionaryValue* file_systems_per_extension = NULL;
385740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  if (!file_systems->GetDictionaryWithoutPathExpansion(
386740d490593e0de8732a697c9f77b90ddd463863bJordan Rose          extension_id, &file_systems_per_extension))
387740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    return;  // Nothing to restore.
388740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
389b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose  // Use a copy of the dictionary, since the original one may be modified while
3907c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  // iterating over it.
3917c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  scoped_ptr<const base::DictionaryValue> file_systems_per_extension_copy(
392b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose      file_systems_per_extension->DeepCopy());
3937c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
3947c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose  for (base::DictionaryValue::Iterator it(*file_systems_per_extension_copy);
395972a3680bdd95f2e9d6316b391f1c47513dc78ccJordan Rose       !it.IsAtEnd();
396740d490593e0de8732a697c9f77b90ddd463863bJordan Rose       it.Advance()) {
397740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    const base::Value* file_system_value = NULL;
398b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose    const base::DictionaryValue* file_system = NULL;
399b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose    file_systems_per_extension_copy->GetWithoutPathExpansion(
4007c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose        it.key(), &file_system_value);
4017c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose    DCHECK(file_system_value);
402b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose
403740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    std::string file_system_id;
404ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek    std::string display_name;
405ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose    bool writable;
406a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
407a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek    if (!file_system_value->GetAsDictionary(&file_system) ||
408a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek        !file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId,
409ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek                                                    &file_system_id) ||
410ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek        !file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName,
411ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek                                                    &display_name) ||
412a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek        !file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable,
413a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek                                                     &writable) ||
414a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek        file_system_id.empty() || display_name.empty()) {
415a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek      LOG(ERROR)
416e90d3f847dcce76237078b67db8895eb7a24189eAnna Zaks          << "Malformed provided file system information in preferences.";
417ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose      continue;
418ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose    }
4197c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose
420b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose    const bool result =
421ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose        MountFileSystem(extension_id, file_system_id, display_name, writable);
422ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose    if (!result) {
423ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose      LOG(ERROR) << "Failed to restore a provided file system from "
424ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose                 << "preferences: " << extension_id << ", " << file_system_id
425ef15831780b705475e7b237ac16418e9b53cb7a6Jordan Rose                 << ", " << display_name << ".";
426b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose      // Since remounting of the file system failed, then remove it from
427740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      // preferences to avoid remounting it over and over again with a failure.
428740d490593e0de8732a697c9f77b90ddd463863bJordan Rose      ForgetFileSystem(extension_id, file_system_id);
429740d490593e0de8732a697c9f77b90ddd463863bJordan Rose    }
430740d490593e0de8732a697c9f77b90ddd463863bJordan Rose  }
431740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}
432740d490593e0de8732a697c9f77b90ddd463863bJordan Rose
433645baeed6800f952e9ad1d5666e01080385531a2Jordan Rose}  // namespace file_system_provider
434740d490593e0de8732a697c9f77b90ddd463863bJordan Rose}  // namespace chromeos
435740d490593e0de8732a697c9f77b90ddd463863bJordan Rose