Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / registry.cc
blobc0bf95d30f7af5fb9f4d4503476064269aa826fd
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
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/file_system_provider/registry.h"
7 #include "base/files/file_path.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/stl_util.h"
11 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
12 #include "chrome/browser/chromeos/file_system_provider/observer.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"
15 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/pref_registry/pref_registry_syncable.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/browser/extension_system.h"
21 #include "storage/browser/fileapi/external_mount_points.h"
23 namespace chromeos {
24 namespace file_system_provider {
26 const char kPrefKeyFileSystemId[] = "file-system-id";
27 const char kPrefKeyDisplayName[] = "display-name";
28 const char kPrefKeyWritable[] = "writable";
29 const char kPrefKeySupportsNotifyTag[] = "supports-notify-tag";
30 const char kPrefKeyWatchers[] = "watchers";
31 const char kPrefKeyWatcherEntryPath[] = "entry-path";
32 const char kPrefKeyWatcherRecursive[] = "recursive";
33 const char kPrefKeyWatcherLastTag[] = "last-tag";
34 const char kPrefKeyWatcherPersistentOrigins[] = "persistent-origins";
35 const char kPrefKeyOpenedFilesLimit[] = "opened-files-limit";
37 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
38 registry->RegisterDictionaryPref(
39 prefs::kFileSystemProviderMounted,
40 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
43 Registry::Registry(Profile* profile) : profile_(profile) {
46 Registry::~Registry() {
49 void Registry::RememberFileSystem(
50 const ProvidedFileSystemInfo& file_system_info,
51 const Watchers& watchers) {
52 base::DictionaryValue* const file_system = new base::DictionaryValue();
53 file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId,
54 file_system_info.file_system_id());
55 file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName,
56 file_system_info.display_name());
57 file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable,
58 file_system_info.writable());
59 file_system->SetBooleanWithoutPathExpansion(
60 kPrefKeySupportsNotifyTag, file_system_info.supports_notify_tag());
61 file_system->SetIntegerWithoutPathExpansion(
62 kPrefKeyOpenedFilesLimit, file_system_info.opened_files_limit());
64 base::DictionaryValue* const watchers_value = new base::DictionaryValue();
65 file_system->SetWithoutPathExpansion(kPrefKeyWatchers, watchers_value);
67 for (const auto& it : watchers) {
68 base::DictionaryValue* const watcher = new base::DictionaryValue();
69 watchers_value->SetWithoutPathExpansion(it.second.entry_path.value(),
70 watcher);
71 watcher->SetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath,
72 it.second.entry_path.value());
73 watcher->SetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive,
74 it.second.recursive);
75 watcher->SetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
76 it.second.last_tag);
77 base::ListValue* const persistent_origins_value = new base::ListValue();
78 watcher->SetWithoutPathExpansion(kPrefKeyWatcherPersistentOrigins,
79 persistent_origins_value);
80 for (const auto& subscriber_it : it.second.subscribers) {
81 // Only persistent subscribers should be stored in persistent storage.
82 // Other ones should not be restired after a restart.
83 if (subscriber_it.second.persistent)
84 persistent_origins_value->AppendString(subscriber_it.first.spec());
88 PrefService* const pref_service = profile_->GetPrefs();
89 DCHECK(pref_service);
91 DictionaryPrefUpdate dict_update(pref_service,
92 prefs::kFileSystemProviderMounted);
94 base::DictionaryValue* file_systems_per_extension = NULL;
95 if (!dict_update->GetDictionaryWithoutPathExpansion(
96 file_system_info.extension_id(), &file_systems_per_extension)) {
97 file_systems_per_extension = new base::DictionaryValue();
98 dict_update->SetWithoutPathExpansion(file_system_info.extension_id(),
99 file_systems_per_extension);
102 file_systems_per_extension->SetWithoutPathExpansion(
103 file_system_info.file_system_id(), file_system);
106 void Registry::ForgetFileSystem(const std::string& extension_id,
107 const std::string& file_system_id) {
108 PrefService* const pref_service = profile_->GetPrefs();
109 DCHECK(pref_service);
111 DictionaryPrefUpdate dict_update(pref_service,
112 prefs::kFileSystemProviderMounted);
114 base::DictionaryValue* file_systems_per_extension = NULL;
115 if (!dict_update->GetDictionaryWithoutPathExpansion(
116 extension_id, &file_systems_per_extension))
117 return; // Nothing to forget.
119 file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL);
120 if (!file_systems_per_extension->size())
121 dict_update->Remove(extension_id, NULL);
124 scoped_ptr<Registry::RestoredFileSystems> Registry::RestoreFileSystems(
125 const std::string& extension_id) {
126 PrefService* const pref_service = profile_->GetPrefs();
127 DCHECK(pref_service);
129 const base::DictionaryValue* const file_systems =
130 pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
131 DCHECK(file_systems);
133 const base::DictionaryValue* file_systems_per_extension = NULL;
134 if (!file_systems->GetDictionaryWithoutPathExpansion(
135 extension_id, &file_systems_per_extension)) {
136 return make_scoped_ptr(new RestoredFileSystems); // Nothing to restore.
139 scoped_ptr<RestoredFileSystems> restored_file_systems(
140 new RestoredFileSystems);
142 for (base::DictionaryValue::Iterator it(*file_systems_per_extension);
143 !it.IsAtEnd();
144 it.Advance()) {
145 const base::Value* file_system_value = NULL;
146 const base::DictionaryValue* file_system = NULL;
147 file_systems_per_extension->GetWithoutPathExpansion(it.key(),
148 &file_system_value);
149 DCHECK(file_system_value);
151 std::string file_system_id;
152 std::string display_name;
153 bool writable = false;
154 bool supports_notify_tag = false;
155 int opened_files_limit = 0;
157 // TODO(mtomasz): Move opened files limit to the mandatory list above in
158 // M42.
159 if ((!file_system_value->GetAsDictionary(&file_system) ||
160 !file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId,
161 &file_system_id) ||
162 !file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName,
163 &display_name) ||
164 !file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable,
165 &writable) ||
166 !file_system->GetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag,
167 &supports_notify_tag) ||
168 file_system_id.empty() || display_name.empty()) ||
169 (file_system->GetIntegerWithoutPathExpansion(kPrefKeyOpenedFilesLimit,
170 &opened_files_limit) &&
171 opened_files_limit < 0)) {
172 LOG(ERROR)
173 << "Malformed provided file system information in preferences.";
174 continue;
177 MountOptions options;
178 options.file_system_id = file_system_id;
179 options.display_name = display_name;
180 options.writable = writable;
181 options.supports_notify_tag = supports_notify_tag;
182 options.opened_files_limit = opened_files_limit;
184 RestoredFileSystem restored_file_system;
185 restored_file_system.extension_id = extension_id;
186 restored_file_system.options = options;
188 // Restore watchers. It's optional, since this field is new.
189 const base::DictionaryValue* watchers = NULL;
190 if (file_system->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers,
191 &watchers)) {
192 for (base::DictionaryValue::Iterator it(*watchers); !it.IsAtEnd();
193 it.Advance()) {
194 const base::Value* watcher_value = NULL;
195 const base::DictionaryValue* watcher = NULL;
196 watchers->GetWithoutPathExpansion(it.key(), &watcher_value);
197 DCHECK(file_system_value);
199 std::string entry_path;
200 bool recursive = false;
201 std::string last_tag;
202 const base::ListValue* persistent_origins = NULL;
204 if (!watcher_value->GetAsDictionary(&watcher) ||
205 !watcher->GetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath,
206 &entry_path) ||
207 !watcher->GetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive,
208 &recursive) ||
209 !watcher->GetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
210 &last_tag) ||
211 !watcher->GetListWithoutPathExpansion(
212 kPrefKeyWatcherPersistentOrigins, &persistent_origins) ||
213 it.key() != entry_path || entry_path.empty() ||
214 (!options.supports_notify_tag &&
215 (!last_tag.empty() || persistent_origins->GetSize()))) {
216 LOG(ERROR) << "Malformed watcher information in preferences.";
217 continue;
220 Watcher restored_watcher;
221 restored_watcher.entry_path =
222 base::FilePath::FromUTF8Unsafe(entry_path);
223 restored_watcher.recursive = recursive;
224 restored_watcher.last_tag = last_tag;
225 for (const auto& persistent_origin : *persistent_origins) {
226 std::string origin;
227 if (persistent_origin->GetAsString(&origin)) {
228 LOG(ERROR) << "Malformed subscriber information in preferences.";
229 continue;
231 const GURL origin_as_gurl(origin);
232 restored_watcher.subscribers[origin_as_gurl].origin = origin_as_gurl;
233 restored_watcher.subscribers[origin_as_gurl].persistent = true;
235 restored_file_system.watchers[WatcherKey(
236 base::FilePath::FromUTF8Unsafe(entry_path), recursive)] =
237 restored_watcher;
240 restored_file_systems->push_back(restored_file_system);
243 return restored_file_systems.Pass();
246 void Registry::UpdateWatcherTag(const ProvidedFileSystemInfo& file_system_info,
247 const Watcher& watcher) {
248 PrefService* const pref_service = profile_->GetPrefs();
249 DCHECK(pref_service);
251 // TODO(mtomasz): Consider optimizing it by moving information about watchers
252 // or even file systems to leveldb.
253 DictionaryPrefUpdate dict_update(pref_service,
254 prefs::kFileSystemProviderMounted);
256 // All of the following checks should not happen in healthy environment.
257 // However, since they rely on storage, DCHECKs can't be used.
258 base::DictionaryValue* file_systems_per_extension = NULL;
259 base::DictionaryValue* file_system = NULL;
260 base::DictionaryValue* watchers = NULL;
261 base::DictionaryValue* watcher_value = NULL;
262 if (!dict_update->GetDictionaryWithoutPathExpansion(
263 file_system_info.extension_id(), &file_systems_per_extension) ||
264 !file_systems_per_extension->GetDictionaryWithoutPathExpansion(
265 file_system_info.file_system_id(), &file_system) ||
266 !file_system->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers,
267 &watchers) ||
268 !watchers->GetDictionaryWithoutPathExpansion(watcher.entry_path.value(),
269 &watcher_value)) {
270 // Broken preferences.
271 LOG(ERROR) << "Broken preferences detected while updating a tag.";
272 return;
275 watcher_value->SetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
276 watcher.last_tag);
279 } // namespace file_system_provider
280 } // namespace chromeos