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

Side by Side Diff: chrome/browser/extensions/api/storage/syncable_settings_storage.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
« no previous file with comments | « chrome/browser/extensions/api/storage/syncable_settings_storage.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/syncable_settings_storage.h" 5 #include "chrome/browser/extensions/api/storage/syncable_settings_storage.h"
6 6
7 #include "base/strings/stringprintf.h" 7 #include "base/strings/stringprintf.h"
8 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h" 8 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h"
9 #include "chrome/browser/extensions/api/storage/settings_sync_util.h" 9 #include "chrome/browser/extensions/api/storage/settings_sync_util.h"
10 #include "content/public/browser/browser_thread.h" 10 #include "content/public/browser/browser_thread.h"
11 #include "extensions/browser/api/storage/settings_namespace.h" 11 #include "extensions/browser/api/storage/settings_namespace.h"
12 #include "sync/api/sync_data.h" 12 #include "sync/api/sync_data.h"
13 #include "sync/protocol/extension_setting_specifics.pb.h" 13 #include "sync/protocol/extension_setting_specifics.pb.h"
14 14
15 using content::BrowserThread;
16
15 namespace extensions { 17 namespace extensions {
16 18
17 using content::BrowserThread;
18
19 SyncableSettingsStorage::SyncableSettingsStorage( 19 SyncableSettingsStorage::SyncableSettingsStorage(
20 const scoped_refptr<ObserverListThreadSafe<SettingsObserver> >& 20 const scoped_refptr<ObserverListThreadSafe<SettingsObserver> >&
21 observers, 21 observers,
22 const std::string& extension_id, 22 const std::string& extension_id,
23 ValueStore* delegate, 23 ValueStore* delegate,
24 syncer::ModelType sync_type, 24 syncer::ModelType sync_type,
25 const syncer::SyncableService::StartSyncFlare& flare) 25 const syncer::SyncableService::StartSyncFlare& flare)
26 : observers_(observers), 26 : observers_(observers),
27 extension_id_(extension_id), 27 extension_id_(extension_id),
28 delegate_(delegate), 28 delegate_(delegate),
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 // Tell sync to try and start soon, because syncable changes to sync_type_ 157 // Tell sync to try and start soon, because syncable changes to sync_type_
158 // have started happening. This will cause sync to call us back 158 // have started happening. This will cause sync to call us back
159 // asynchronously via StartSyncing(...) as soon as possible. 159 // asynchronously via StartSyncing(...) as soon as possible.
160 flare_.Run(sync_type_); 160 flare_.Run(sync_type_);
161 } 161 }
162 } 162 }
163 163
164 // Sync-related methods. 164 // Sync-related methods.
165 165
166 syncer::SyncError SyncableSettingsStorage::StartSyncing( 166 syncer::SyncError SyncableSettingsStorage::StartSyncing(
167 const base::DictionaryValue& sync_state, 167 scoped_ptr<base::DictionaryValue> sync_state,
168 scoped_ptr<SettingsSyncProcessor> sync_processor) { 168 scoped_ptr<SettingsSyncProcessor> sync_processor) {
169 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 169 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
170 DCHECK(sync_state);
170 DCHECK(!sync_processor_.get()); 171 DCHECK(!sync_processor_.get());
171 172
172 sync_processor_ = sync_processor.Pass(); 173 sync_processor_ = sync_processor.Pass();
173 sync_processor_->Init(sync_state); 174 sync_processor_->Init(*sync_state);
174 175
175 ReadResult maybe_settings = delegate_->Get(); 176 ReadResult maybe_settings = delegate_->Get();
176 if (maybe_settings->HasError()) { 177 if (maybe_settings->HasError()) {
177 return syncer::SyncError( 178 return syncer::SyncError(
178 FROM_HERE, 179 FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
179 syncer::SyncError::DATATYPE_ERROR,
180 base::StringPrintf("Failed to get settings: %s", 180 base::StringPrintf("Failed to get settings: %s",
181 maybe_settings->error().message.c_str()), 181 maybe_settings->error().message.c_str()),
182 sync_processor_->type()); 182 sync_processor_->type());
183 } 183 }
184 184
185 const base::DictionaryValue& settings = maybe_settings->settings(); 185 scoped_ptr<base::DictionaryValue> current_settings =
186 return sync_state.empty() ? 186 maybe_settings->PassSettings();
187 SendLocalSettingsToSync(settings) : 187 return sync_state->empty() ? SendLocalSettingsToSync(current_settings.Pass())
188 OverwriteLocalSettingsWithSync(sync_state, settings); 188 : OverwriteLocalSettingsWithSync(
189 sync_state.Pass(), current_settings.Pass());
189 } 190 }
190 191
191 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync( 192 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync(
192 const base::DictionaryValue& settings) { 193 scoped_ptr<base::DictionaryValue> local_state) {
193 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 194 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
194 195
196 if (local_state->empty())
197 return syncer::SyncError();
198
199 // Transform the current settings into a list of sync changes.
195 ValueStoreChangeList changes; 200 ValueStoreChangeList changes;
196 for (base::DictionaryValue::Iterator i(settings); !i.IsAtEnd(); i.Advance()) { 201 while (!local_state->empty()) {
197 changes.push_back(ValueStoreChange(i.key(), NULL, i.value().DeepCopy())); 202 // It's not possible to iterate over a DictionaryValue and modify it at the
203 // same time, so hack around that restriction.
204 std::string key = base::DictionaryValue::Iterator(*local_state).key();
205 scoped_ptr<base::Value> value;
206 local_state->RemoveWithoutPathExpansion(key, &value);
207 changes.push_back(ValueStoreChange(key, nullptr, value.release()));
198 } 208 }
199 209
200 if (changes.empty())
201 return syncer::SyncError();
202
203 syncer::SyncError error = sync_processor_->SendChanges(changes); 210 syncer::SyncError error = sync_processor_->SendChanges(changes);
204 if (error.IsSet()) 211 if (error.IsSet())
205 StopSyncing(); 212 StopSyncing();
206
207 return error; 213 return error;
208 } 214 }
209 215
210 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync( 216 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync(
211 const base::DictionaryValue& sync_state, 217 scoped_ptr<base::DictionaryValue> sync_state,
212 const base::DictionaryValue& settings) { 218 scoped_ptr<base::DictionaryValue> local_state) {
213 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 219 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
214 // Treat this as a list of changes to sync and use ProcessSyncChanges. 220 // This is implemented by building up a list of sync changes then sending
215 // This gives notifications etc for free. 221 // those to ProcessSyncChanges. This generates events like onStorageChanged.
216 scoped_ptr<base::DictionaryValue> new_sync_state(sync_state.DeepCopy()); 222 scoped_ptr<SettingSyncDataList> changes(new SettingSyncDataList());
217 223
218 SettingSyncDataList changes; 224 for (base::DictionaryValue::Iterator it(*local_state); !it.IsAtEnd();
219 for (base::DictionaryValue::Iterator it(settings); 225 it.Advance()) {
220 !it.IsAtEnd(); it.Advance()) {
221 scoped_ptr<base::Value> sync_value; 226 scoped_ptr<base::Value> sync_value;
222 if (new_sync_state->RemoveWithoutPathExpansion(it.key(), &sync_value)) { 227 if (sync_state->RemoveWithoutPathExpansion(it.key(), &sync_value)) {
223 if (sync_value->Equals(&it.value())) { 228 if (sync_value->Equals(&it.value())) {
224 // Sync and local values are the same, no changes to send. 229 // Sync and local values are the same, no changes to send.
225 } else { 230 } else {
226 // Sync value is different, update local setting with new value. 231 // Sync value is different, update local setting with new value.
227 changes.push_back( 232 changes->push_back(
228 SettingSyncData( 233 new SettingSyncData(syncer::SyncChange::ACTION_UPDATE,
229 syncer::SyncChange::ACTION_UPDATE, 234 extension_id_, it.key(), sync_value.Pass()));
230 extension_id_,
231 it.key(),
232 sync_value.Pass()));
233 } 235 }
234 } else { 236 } else {
235 // Not synced, delete local setting. 237 // Not synced, delete local setting.
236 changes.push_back( 238 changes->push_back(new SettingSyncData(
237 SettingSyncData( 239 syncer::SyncChange::ACTION_DELETE, extension_id_, it.key(),
238 syncer::SyncChange::ACTION_DELETE, 240 scoped_ptr<base::Value>(new base::DictionaryValue())));
239 extension_id_,
240 it.key(),
241 scoped_ptr<base::Value>(new base::DictionaryValue())));
242 } 241 }
243 } 242 }
244 243
245 // Add all new settings to local settings. 244 // Add all new settings to local settings.
246 while (!new_sync_state->empty()) { 245 while (!sync_state->empty()) {
247 base::DictionaryValue::Iterator first_entry(*new_sync_state); 246 // It's not possible to iterate over a DictionaryValue and modify it at the
248 std::string key = first_entry.key(); 247 // same time, so hack around that restriction.
248 std::string key = base::DictionaryValue::Iterator(*sync_state).key();
249 scoped_ptr<base::Value> value; 249 scoped_ptr<base::Value> value;
250 CHECK(new_sync_state->RemoveWithoutPathExpansion(key, &value)); 250 CHECK(sync_state->RemoveWithoutPathExpansion(key, &value));
251 changes.push_back( 251 changes->push_back(new SettingSyncData(syncer::SyncChange::ACTION_ADD,
252 SettingSyncData( 252 extension_id_, key, value.Pass()));
253 syncer::SyncChange::ACTION_ADD,
254 extension_id_,
255 key,
256 value.Pass()));
257 } 253 }
258 254
259 if (changes.empty()) 255 if (changes->empty())
260 return syncer::SyncError(); 256 return syncer::SyncError();
261 257 return ProcessSyncChanges(changes.Pass());
262 return ProcessSyncChanges(changes);
263 } 258 }
264 259
265 void SyncableSettingsStorage::StopSyncing() { 260 void SyncableSettingsStorage::StopSyncing() {
266 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 261 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
267 sync_processor_.reset(); 262 sync_processor_.reset();
268 } 263 }
269 264
270 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges( 265 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges(
271 const SettingSyncDataList& sync_changes) { 266 scoped_ptr<SettingSyncDataList> sync_changes) {
272 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 267 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
273 DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_; 268 DCHECK(!sync_changes->empty()) << "No sync changes for " << extension_id_;
274 269
275 if (!sync_processor_.get()) { 270 if (!sync_processor_.get()) {
276 return syncer::SyncError( 271 return syncer::SyncError(
277 FROM_HERE, 272 FROM_HERE,
278 syncer::SyncError::DATATYPE_ERROR, 273 syncer::SyncError::DATATYPE_ERROR,
279 std::string("Sync is inactive for ") + extension_id_, 274 std::string("Sync is inactive for ") + extension_id_,
280 syncer::UNSPECIFIED); 275 syncer::UNSPECIFIED);
281 } 276 }
282 277
283 std::vector<syncer::SyncError> errors; 278 std::vector<syncer::SyncError> errors;
284 ValueStoreChangeList changes; 279 ValueStoreChangeList changes;
285 280
286 for (SettingSyncDataList::const_iterator it = sync_changes.begin(); 281 for (SettingSyncDataList::iterator it = sync_changes->begin();
287 it != sync_changes.end(); ++it) { 282 it != sync_changes->end(); ++it) {
288 DCHECK_EQ(extension_id_, it->extension_id()); 283 DCHECK_EQ(extension_id_, (*it)->extension_id());
289 284 const std::string& key = (*it)->key();
290 const std::string& key = it->key(); 285 scoped_ptr<base::Value> change_value = (*it)->PassValue();
291 const base::Value& value = it->value();
292 286
293 scoped_ptr<base::Value> current_value; 287 scoped_ptr<base::Value> current_value;
294 { 288 {
295 ReadResult maybe_settings = Get(it->key()); 289 ReadResult maybe_settings = Get(key);
296 if (maybe_settings->HasError()) { 290 if (maybe_settings->HasError()) {
297 errors.push_back(syncer::SyncError( 291 errors.push_back(syncer::SyncError(
298 FROM_HERE, 292 FROM_HERE,
299 syncer::SyncError::DATATYPE_ERROR, 293 syncer::SyncError::DATATYPE_ERROR,
300 base::StringPrintf("Error getting current sync state for %s/%s: %s", 294 base::StringPrintf("Error getting current sync state for %s/%s: %s",
301 extension_id_.c_str(), key.c_str(), 295 extension_id_.c_str(), key.c_str(),
302 maybe_settings->error().message.c_str()), 296 maybe_settings->error().message.c_str()),
303 sync_processor_->type())); 297 sync_processor_->type()));
304 continue; 298 continue;
305 } 299 }
306 maybe_settings->settings().RemoveWithoutPathExpansion(key, 300 maybe_settings->settings().RemoveWithoutPathExpansion(key,
307 &current_value); 301 &current_value);
308 } 302 }
309 303
310 syncer::SyncError error; 304 syncer::SyncError error;
311 305
312 switch (it->change_type()) { 306 switch ((*it)->change_type()) {
313 case syncer::SyncChange::ACTION_ADD: 307 case syncer::SyncChange::ACTION_ADD:
314 if (!current_value.get()) { 308 if (!current_value.get()) {
315 error = OnSyncAdd(key, value.DeepCopy(), &changes); 309 error = OnSyncAdd(key, change_value.release(), &changes);
316 } else { 310 } else {
317 // Already a value; hopefully a local change has beaten sync in a 311 // Already a value; hopefully a local change has beaten sync in a
318 // race and it's not a bug, so pretend it's an update. 312 // race and change's not a bug, so pretend change's an update.
319 LOG(WARNING) << "Got add from sync for existing setting " << 313 LOG(WARNING) << "Got add from sync for existing setting " <<
320 extension_id_ << "/" << key; 314 extension_id_ << "/" << key;
321 error = OnSyncUpdate( 315 error = OnSyncUpdate(key, current_value.release(),
322 key, current_value.release(), value.DeepCopy(), &changes); 316 change_value.release(), &changes);
323 } 317 }
324 break; 318 break;
325 319
326 case syncer::SyncChange::ACTION_UPDATE: 320 case syncer::SyncChange::ACTION_UPDATE:
327 if (current_value.get()) { 321 if (current_value.get()) {
328 error = OnSyncUpdate( 322 error = OnSyncUpdate(key, current_value.release(),
329 key, current_value.release(), value.DeepCopy(), &changes); 323 change_value.release(), &changes);
330 } else { 324 } else {
331 // Similarly, pretend it's an add. 325 // Similarly, pretend change's an add.
332 LOG(WARNING) << "Got update from sync for nonexistent setting" << 326 LOG(WARNING) << "Got update from sync for nonexistent setting" <<
333 extension_id_ << "/" << key; 327 extension_id_ << "/" << key;
334 error = OnSyncAdd(key, value.DeepCopy(), &changes); 328 error = OnSyncAdd(key, change_value.release(), &changes);
335 } 329 }
336 break; 330 break;
337 331
338 case syncer::SyncChange::ACTION_DELETE: 332 case syncer::SyncChange::ACTION_DELETE:
339 if (current_value.get()) { 333 if (current_value.get()) {
340 error = OnSyncDelete(key, current_value.release(), &changes); 334 error = OnSyncDelete(key, current_value.release(), &changes);
341 } else { 335 } else {
342 // Similarly, ignore it. 336 // Similarly, ignore change.
343 LOG(WARNING) << "Got delete from sync for nonexistent setting " << 337 LOG(WARNING) << "Got delete from sync for nonexistent setting " <<
344 extension_id_ << "/" << key; 338 extension_id_ << "/" << key;
345 } 339 }
346 break; 340 break;
347 341
348 default: 342 default:
349 NOTREACHED(); 343 NOTREACHED();
350 } 344 }
351 345
352 if (error.IsSet()) { 346 if (error.IsSet()) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 syncer::SyncError::DATATYPE_ERROR, 408 syncer::SyncError::DATATYPE_ERROR,
415 base::StringPrintf("Error pushing sync remove to local settings: %s", 409 base::StringPrintf("Error pushing sync remove to local settings: %s",
416 result->error().message.c_str()), 410 result->error().message.c_str()),
417 sync_processor_->type()); 411 sync_processor_->type());
418 } 412 }
419 changes->push_back(ValueStoreChange(key, old_value, NULL)); 413 changes->push_back(ValueStoreChange(key, old_value, NULL));
420 return syncer::SyncError(); 414 return syncer::SyncError();
421 } 415 }
422 416
423 } // namespace extensions 417 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/storage/syncable_settings_storage.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698