Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / registry.cc
blobe301279b6762deb87b2be57b6d772c1932ad7e7f
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(prefs::kFileSystemProviderMounted);
41 Registry::Registry(Profile* profile) : profile_(profile) {
44 Registry::~Registry() {
47 void Registry::RememberFileSystem(
48 const ProvidedFileSystemInfo& file_system_info,
49 const Watchers& watchers) {
50 base::DictionaryValue* const file_system = new base::DictionaryValue();
51 file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId,
52 file_system_info.file_system_id());
53 file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName,
54 file_system_info.display_name());
55 file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable,
56 file_system_info.writable());
57 file_system->SetBooleanWithoutPathExpansion(
58 kPrefKeySupportsNotifyTag, file_system_info.supports_notify_tag());
59 file_system->SetIntegerWithoutPathExpansion(
60 kPrefKeyOpenedFilesLimit, file_system_info.opened_files_limit());
62 base::DictionaryValue* const watchers_value = new base::DictionaryValue();
63 file_system->SetWithoutPathExpansion(kPrefKeyWatchers, watchers_value);
65 for (const auto& it : watchers) {
66 base::DictionaryValue* const watcher = new base::DictionaryValue();
67 watchers_value->SetWithoutPathExpansion(it.second.entry_path.value(),
68 watcher);
69 watcher->SetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath,
70 it.second.entry_path.value());
71 watcher->SetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive,
72 it.second.recursive);
73 watcher->SetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
74 it.second.last_tag);
75 base::ListValue* const persistent_origins_value = new base::ListValue();
76 watcher->SetWithoutPathExpansion(kPrefKeyWatcherPersistentOrigins,
77 persistent_origins_value);
78 for (const auto& subscriber_it : it.second.subscribers) {
79 // Only persistent subscribers should be stored in persistent storage.
80 // Other ones should not be restired after a restart.
81 if (subscriber_it.second.persistent)
82 persistent_origins_value->AppendString(subscriber_it.first.spec());
86 PrefService* const pref_service = profile_->GetPrefs();
87 DCHECK(pref_service);
89 DictionaryPrefUpdate dict_update(pref_service,
90 prefs::kFileSystemProviderMounted);
92 base::DictionaryValue* file_systems_per_extension = NULL;
93 if (!dict_update->GetDictionaryWithoutPathExpansion(
94 file_system_info.extension_id(), &file_systems_per_extension)) {
95 file_systems_per_extension = new base::DictionaryValue();
96 dict_update->SetWithoutPathExpansion(file_system_info.extension_id(),
97 file_systems_per_extension);
100 file_systems_per_extension->SetWithoutPathExpansion(
101 file_system_info.file_system_id(), file_system);
104 void Registry::ForgetFileSystem(const std::string& extension_id,
105 const std::string& file_system_id) {
106 PrefService* const pref_service = profile_->GetPrefs();
107 DCHECK(pref_service);
109 DictionaryPrefUpdate dict_update(pref_service,
110 prefs::kFileSystemProviderMounted);
112 base::DictionaryValue* file_systems_per_extension = NULL;
113 if (!dict_update->GetDictionaryWithoutPathExpansion(
114 extension_id, &file_systems_per_extension))
115 return; // Nothing to forget.
117 file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL);
118 if (!file_systems_per_extension->size())
119 dict_update->Remove(extension_id, NULL);
122 scoped_ptr<Registry::RestoredFileSystems> Registry::RestoreFileSystems(
123 const std::string& extension_id) {
124 PrefService* const pref_service = profile_->GetPrefs();
125 DCHECK(pref_service);
127 const base::DictionaryValue* const file_systems =
128 pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
129 DCHECK(file_systems);
131 const base::DictionaryValue* file_systems_per_extension = NULL;
132 if (!file_systems->GetDictionaryWithoutPathExpansion(
133 extension_id, &file_systems_per_extension)) {
134 return make_scoped_ptr(new RestoredFileSystems); // Nothing to restore.
137 scoped_ptr<RestoredFileSystems> restored_file_systems(
138 new RestoredFileSystems);
140 for (base::DictionaryValue::Iterator it(*file_systems_per_extension);
141 !it.IsAtEnd();
142 it.Advance()) {
143 const base::Value* file_system_value = NULL;
144 const base::DictionaryValue* file_system = NULL;
145 file_systems_per_extension->GetWithoutPathExpansion(it.key(),
146 &file_system_value);
147 DCHECK(file_system_value);
149 std::string file_system_id;
150 std::string display_name;
151 bool writable = false;
152 bool supports_notify_tag = false;
153 int opened_files_limit = 0;
155 // TODO(mtomasz): Move opened files limit to the mandatory list above in
156 // M42.
157 if ((!file_system_value->GetAsDictionary(&file_system) ||
158 !file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId,
159 &file_system_id) ||
160 !file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName,
161 &display_name) ||
162 !file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable,
163 &writable) ||
164 !file_system->GetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag,
165 &supports_notify_tag) ||
166 file_system_id.empty() || display_name.empty()) ||
167 // Optional fields.
168 (file_system->GetIntegerWithoutPathExpansion(kPrefKeyOpenedFilesLimit,
169 &opened_files_limit) &&
170 opened_files_limit < 0)) {
171 LOG(ERROR)
172 << "Malformed provided file system information in preferences.";
173 continue;
176 MountOptions options;
177 options.file_system_id = file_system_id;
178 options.display_name = display_name;
179 options.writable = writable;
180 options.supports_notify_tag = supports_notify_tag;
181 options.opened_files_limit = opened_files_limit;
183 RestoredFileSystem restored_file_system;
184 restored_file_system.extension_id = extension_id;
185 restored_file_system.options = options;
187 // Restore watchers. It's optional, since this field is new.
188 const base::DictionaryValue* watchers = NULL;
189 if (file_system->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers,
190 &watchers)) {
191 for (base::DictionaryValue::Iterator it(*watchers); !it.IsAtEnd();
192 it.Advance()) {
193 const base::Value* watcher_value = NULL;
194 const base::DictionaryValue* watcher = NULL;
195 watchers->GetWithoutPathExpansion(it.key(), &watcher_value);
196 DCHECK(file_system_value);
198 std::string entry_path;
199 bool recursive = false;
200 std::string last_tag;
201 const base::ListValue* persistent_origins = NULL;
203 if (!watcher_value->GetAsDictionary(&watcher) ||
204 !watcher->GetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath,
205 &entry_path) ||
206 !watcher->GetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive,
207 &recursive) ||
208 !watcher->GetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
209 &last_tag) ||
210 !watcher->GetListWithoutPathExpansion(
211 kPrefKeyWatcherPersistentOrigins, &persistent_origins) ||
212 it.key() != entry_path || entry_path.empty() ||
213 (!options.supports_notify_tag &&
214 (!last_tag.empty() || persistent_origins->GetSize()))) {
215 LOG(ERROR) << "Malformed watcher information in preferences.";
216 continue;
219 Watcher restored_watcher;
220 restored_watcher.entry_path =
221 base::FilePath::FromUTF8Unsafe(entry_path);
222 restored_watcher.recursive = recursive;
223 restored_watcher.last_tag = last_tag;
224 for (const auto& persistent_origin : *persistent_origins) {
225 std::string origin;
226 if (persistent_origin->GetAsString(&origin)) {
227 LOG(ERROR) << "Malformed subscriber information in preferences.";
228 continue;
230 const GURL origin_as_gurl(origin);
231 restored_watcher.subscribers[origin_as_gurl].origin = origin_as_gurl;
232 restored_watcher.subscribers[origin_as_gurl].persistent = true;
234 restored_file_system.watchers[WatcherKey(
235 base::FilePath::FromUTF8Unsafe(entry_path), recursive)] =
236 restored_watcher;
239 restored_file_systems->push_back(restored_file_system);
242 return restored_file_systems.Pass();
245 void Registry::UpdateWatcherTag(const ProvidedFileSystemInfo& file_system_info,
246 const Watcher& watcher) {
247 PrefService* const pref_service = profile_->GetPrefs();
248 DCHECK(pref_service);
250 // TODO(mtomasz): Consider optimizing it by moving information about watchers
251 // or even file systems to leveldb.
252 DictionaryPrefUpdate dict_update(pref_service,
253 prefs::kFileSystemProviderMounted);
255 // All of the following checks should not happen in healthy environment.
256 // However, since they rely on storage, DCHECKs can't be used.
257 base::DictionaryValue* file_systems_per_extension = NULL;
258 base::DictionaryValue* file_system = NULL;
259 base::DictionaryValue* watchers = NULL;
260 base::DictionaryValue* watcher_value = NULL;
261 if (!dict_update->GetDictionaryWithoutPathExpansion(
262 file_system_info.extension_id(), &file_systems_per_extension) ||
263 !file_systems_per_extension->GetDictionaryWithoutPathExpansion(
264 file_system_info.file_system_id(), &file_system) ||
265 !file_system->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers,
266 &watchers) ||
267 !watchers->GetDictionaryWithoutPathExpansion(watcher.entry_path.value(),
268 &watcher_value)) {
269 // Broken preferences.
270 LOG(ERROR) << "Broken preferences detected while updating a tag.";
271 return;
274 watcher_value->SetStringWithoutPathExpansion(kPrefKeyWatcherLastTag,
275 watcher.last_tag);
278 } // namespace file_system_provider
279 } // namespace chromeos