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

Side by Side Diff: chrome/browser/extensions/api/storage/sync_storage_backend.cc

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

Powered by Google App Engine
This is Rietveld 408576698