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

Side by Side Diff: chrome/browser/extensions/settings/settings_backend.cc

Issue 11747025: Run the JSON Schema Compiler's bundle compilation on JSON files. Previously it (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix ms release build Created 7 years, 11 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "chrome/browser/extensions/settings/settings_backend.h"
6
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "chrome/browser/extensions/settings/settings_sync_processor.h"
10 #include "chrome/browser/extensions/settings/settings_sync_util.h"
11 #include "chrome/browser/extensions/settings/syncable_settings_storage.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "sync/api/sync_error_factory.h"
14
15 using content::BrowserThread;
16
17 namespace extensions {
18
19 SettingsBackend::SettingsBackend(
20 const scoped_refptr<SettingsStorageFactory>& storage_factory,
21 const FilePath& base_path,
22 const SettingsStorageQuotaEnforcer::Limits& quota,
23 const scoped_refptr<SettingsObserverList>& observers)
24 : storage_factory_(storage_factory),
25 base_path_(base_path),
26 quota_(quota),
27 observers_(observers),
28 sync_type_(syncer::UNSPECIFIED) {
29 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
30 }
31
32 SettingsBackend::~SettingsBackend() {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
34 }
35
36 ValueStore* SettingsBackend::GetStorage(
37 const std::string& extension_id) const {
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
39 DictionaryValue empty;
40 return GetOrCreateStorageWithSyncData(extension_id, empty);
41 }
42
43 SyncableSettingsStorage* SettingsBackend::GetOrCreateStorageWithSyncData(
44 const std::string& extension_id, const DictionaryValue& sync_data) const {
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
46
47 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
48 if (maybe_storage != storage_objs_.end()) {
49 return maybe_storage->second.get();
50 }
51
52 ValueStore* storage = storage_factory_->Create(base_path_, extension_id);
53 CHECK(storage);
54
55 // It's fine to create the quota enforcer underneath the sync layer, since
56 // sync will only go ahead if each underlying storage operation succeeds.
57 storage = new SettingsStorageQuotaEnforcer(quota_, storage);
58
59 linked_ptr<SyncableSettingsStorage> syncable_storage(
60 new SyncableSettingsStorage(
61 observers_,
62 extension_id,
63 storage));
64 storage_objs_[extension_id] = syncable_storage;
65
66 if (sync_processor_.get()) {
67 syncer::SyncError error =
68 syncable_storage->StartSyncing(
69 sync_data,
70 CreateSettingsSyncProcessor(extension_id).Pass());
71 if (error.IsSet())
72 syncable_storage.get()->StopSyncing();
73 }
74
75 return syncable_storage.get();
76 }
77
78 void SettingsBackend::DeleteStorage(const std::string& extension_id) {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
80
81 // Clear settings when the extension is uninstalled. Leveldb implementations
82 // will also delete the database from disk when the object is destroyed as a
83 // result of being removed from |storage_objs_|.
84 //
85 // TODO(kalman): always GetStorage here (rather than only clearing if it
86 // exists) since the storage area may have been unloaded, but we still want
87 // to clear the data from disk.
88 // However, this triggers http://crbug.com/111072.
89 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
90 if (maybe_storage == storage_objs_.end())
91 return;
92 maybe_storage->second->Clear();
93 storage_objs_.erase(extension_id);
94 }
95
96 std::set<std::string> SettingsBackend::GetKnownExtensionIDs() const {
97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
98 std::set<std::string> result;
99
100 // Storage areas can be in-memory as well as on disk. |storage_objs_| will
101 // contain all that are in-memory.
102 for (StorageObjMap::iterator it = storage_objs_.begin();
103 it != storage_objs_.end(); ++it) {
104 result.insert(it->first);
105 }
106
107 // Leveldb databases are directories inside base_path_.
108 file_util::FileEnumerator::FindInfo find_info;
109 file_util::FileEnumerator extension_dirs(
110 base_path_, false, file_util::FileEnumerator::DIRECTORIES);
111 while (!extension_dirs.Next().empty()) {
112 extension_dirs.GetFindInfo(&find_info);
113 FilePath extension_dir(file_util::FileEnumerator::GetFilename(find_info));
114 DCHECK(!extension_dir.IsAbsolute());
115 // Extension IDs are created as std::strings so they *should* be ASCII.
116 std::string maybe_as_ascii(extension_dir.MaybeAsASCII());
117 if (!maybe_as_ascii.empty()) {
118 result.insert(maybe_as_ascii);
119 }
120 }
121
122 return result;
123 }
124
125 static void AddAllSyncData(
126 const std::string& extension_id,
127 const DictionaryValue& src,
128 syncer::ModelType type,
129 syncer::SyncDataList* dst) {
130 for (DictionaryValue::Iterator it(src); it.HasNext(); it.Advance()) {
131 dst->push_back(settings_sync_util::CreateData(
132 extension_id, it.key(), it.value(), type));
133 }
134 }
135
136 syncer::SyncDataList SettingsBackend::GetAllSyncData(
137 syncer::ModelType type) const {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
139 // Ignore the type, it's just for sanity checking; assume that whatever base
140 // path we're constructed with is correct for the sync type.
141 DCHECK(type == syncer::EXTENSION_SETTINGS ||
142 type == syncer::APP_SETTINGS);
143
144 // For all extensions, get all their settings. This has the effect
145 // of bringing in the entire state of extension settings in memory; sad.
146 syncer::SyncDataList all_sync_data;
147 std::set<std::string> known_extension_ids(GetKnownExtensionIDs());
148
149 for (std::set<std::string>::const_iterator it = known_extension_ids.begin();
150 it != known_extension_ids.end(); ++it) {
151 ValueStore::ReadResult maybe_settings = GetStorage(*it)->Get();
152 if (maybe_settings->HasError()) {
153 LOG(WARNING) << "Failed to get settings for " << *it << ": " <<
154 maybe_settings->error();
155 continue;
156 }
157 AddAllSyncData(*it, *maybe_settings->settings().get(),
158 type, &all_sync_data);
159 }
160
161 return all_sync_data;
162 }
163
164 syncer::SyncMergeResult SettingsBackend::MergeDataAndStartSyncing(
165 syncer::ModelType type,
166 const syncer::SyncDataList& initial_sync_data,
167 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
168 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
170 DCHECK(type == syncer::EXTENSION_SETTINGS ||
171 type == syncer::APP_SETTINGS);
172 DCHECK_EQ(sync_type_, syncer::UNSPECIFIED);
173 DCHECK(!sync_processor_.get());
174 DCHECK(sync_processor.get());
175 DCHECK(sync_error_factory.get());
176
177 sync_type_ = type;
178 sync_processor_ = sync_processor.Pass();
179 sync_error_factory_ = sync_error_factory.Pass();
180
181 // Group the initial sync data by extension id.
182 std::map<std::string, linked_ptr<DictionaryValue> > grouped_sync_data;
183 for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin();
184 it != initial_sync_data.end(); ++it) {
185 SettingSyncData data(*it);
186 linked_ptr<DictionaryValue> sync_data =
187 grouped_sync_data[data.extension_id()];
188 if (!sync_data.get()) {
189 sync_data = linked_ptr<DictionaryValue>(new DictionaryValue());
190 grouped_sync_data[data.extension_id()] = sync_data;
191 }
192 DCHECK(!sync_data->HasKey(data.key())) <<
193 "Duplicate settings for " << data.extension_id() << "/" << data.key();
194 sync_data->SetWithoutPathExpansion(data.key(), data.value().DeepCopy());
195 }
196
197 // Start syncing all existing storage areas. Any storage areas created in
198 // the future will start being synced as part of the creation process.
199 for (StorageObjMap::iterator it = storage_objs_.begin();
200 it != storage_objs_.end(); ++it) {
201 std::map<std::string, linked_ptr<DictionaryValue> >::iterator
202 maybe_sync_data = grouped_sync_data.find(it->first);
203 syncer::SyncError error;
204 if (maybe_sync_data != grouped_sync_data.end()) {
205 error = it->second->StartSyncing(
206 *maybe_sync_data->second,
207 CreateSettingsSyncProcessor(it->first).Pass());
208 grouped_sync_data.erase(it->first);
209 } else {
210 DictionaryValue empty;
211 error = it->second->StartSyncing(
212 empty,
213 CreateSettingsSyncProcessor(it->first).Pass());
214 }
215 if (error.IsSet())
216 it->second->StopSyncing();
217 }
218
219 // Eagerly create and init the rest of the storage areas that have sync data.
220 // Under normal circumstances (i.e. not first-time sync) this will be all of
221 // them.
222 for (std::map<std::string, linked_ptr<DictionaryValue> >::iterator it =
223 grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) {
224 GetOrCreateStorageWithSyncData(it->first, *it->second);
225 }
226
227 return syncer::SyncMergeResult(type);
228 }
229
230 syncer::SyncError SettingsBackend::ProcessSyncChanges(
231 const tracked_objects::Location& from_here,
232 const syncer::SyncChangeList& sync_changes) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
234 DCHECK(sync_processor_.get());
235
236 // Group changes by extension, to pass all changes in a single method call.
237 std::map<std::string, SettingSyncDataList> grouped_sync_data;
238 for (syncer::SyncChangeList::const_iterator it = sync_changes.begin();
239 it != sync_changes.end(); ++it) {
240 SettingSyncData data(*it);
241 grouped_sync_data[data.extension_id()].push_back(data);
242 }
243
244 // Create any storage areas that don't exist yet but have sync data.
245 DictionaryValue empty;
246 for (std::map<std::string, SettingSyncDataList>::iterator
247 it = grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) {
248 SyncableSettingsStorage* storage =
249 GetOrCreateStorageWithSyncData(it->first, empty);
250 syncer::SyncError error = storage->ProcessSyncChanges(it->second);
251 if (error.IsSet())
252 storage->StopSyncing();
253 }
254
255 return syncer::SyncError();
256 }
257
258 void SettingsBackend::StopSyncing(syncer::ModelType type) {
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
260 DCHECK(type == syncer::EXTENSION_SETTINGS ||
261 type == syncer::APP_SETTINGS);
262 DCHECK(sync_type_ == type || sync_type_ == syncer::UNSPECIFIED);
263
264 for (StorageObjMap::iterator it = storage_objs_.begin();
265 it != storage_objs_.end(); ++it) {
266 // Some storage areas may have already stopped syncing if they had areas
267 // and syncing was disabled, but StopSyncing is safe to call multiple times.
268 it->second->StopSyncing();
269 }
270
271 sync_type_ = syncer::UNSPECIFIED;
272 sync_processor_.reset();
273 sync_error_factory_.reset();
274 }
275
276 scoped_ptr<SettingsSyncProcessor> SettingsBackend::CreateSettingsSyncProcessor(
277 const std::string& extension_id) const {
278 CHECK(sync_processor_.get());
279 return scoped_ptr<SettingsSyncProcessor>(
280 new SettingsSyncProcessor(extension_id,
281 sync_type_,
282 sync_processor_.get()));
283 }
284
285 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/settings/settings_backend.h ('k') | chrome/browser/extensions/settings/settings_frontend.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698