OLD | NEW |
---|---|
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 "components/syncable_prefs/pref_model_associator.h" | 5 #include "components/syncable_prefs/pref_model_associator.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/json/json_string_value_serializer.h" | 9 #include "base/json/json_string_value_serializer.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 pref_service_ = NULL; | 68 pref_service_ = NULL; |
69 | 69 |
70 STLDeleteContainerPairSecondPointers(synced_pref_observers_.begin(), | 70 STLDeleteContainerPairSecondPointers(synced_pref_observers_.begin(), |
71 synced_pref_observers_.end()); | 71 synced_pref_observers_.end()); |
72 synced_pref_observers_.clear(); | 72 synced_pref_observers_.clear(); |
73 } | 73 } |
74 | 74 |
75 void PrefModelAssociator::InitPrefAndAssociate( | 75 void PrefModelAssociator::InitPrefAndAssociate( |
76 const syncer::SyncData& sync_pref, | 76 const syncer::SyncData& sync_pref, |
77 const std::string& pref_name, | 77 const std::string& pref_name, |
78 syncer::SyncChangeList* sync_changes, | 78 syncer::SyncChangeList* sync_changes) { |
79 SyncDataMap* migrated_preference_list) { | |
80 const base::Value* user_pref_value = pref_service_->GetUserPrefValue( | 79 const base::Value* user_pref_value = pref_service_->GetUserPrefValue( |
81 pref_name.c_str()); | 80 pref_name.c_str()); |
82 VLOG(1) << "Associating preference " << pref_name; | 81 VLOG(1) << "Associating preference " << pref_name; |
83 | 82 |
84 if (sync_pref.IsValid()) { | 83 if (sync_pref.IsValid()) { |
85 const sync_pb::PreferenceSpecifics& preference = GetSpecifics(sync_pref); | 84 const sync_pb::PreferenceSpecifics& preference = GetSpecifics(sync_pref); |
86 std::string old_pref_name; | 85 DCHECK(pref_name == preference.name()); |
87 DCHECK(pref_name == preference.name() || | |
88 (client_ && | |
89 client_->IsMigratedPreference(pref_name, &old_pref_name) && | |
90 preference.name() == old_pref_name)); | |
91 base::JSONReader reader; | 86 base::JSONReader reader; |
92 scoped_ptr<base::Value> sync_value(reader.ReadToValue(preference.value())); | 87 scoped_ptr<base::Value> sync_value(reader.ReadToValue(preference.value())); |
93 if (!sync_value.get()) { | 88 if (!sync_value.get()) { |
94 LOG(ERROR) << "Failed to deserialize preference value: " | 89 LOG(ERROR) << "Failed to deserialize preference value: " |
95 << reader.GetErrorMessage(); | 90 << reader.GetErrorMessage(); |
96 return; | 91 return; |
97 } | 92 } |
98 | 93 |
99 if (user_pref_value) { | 94 if (user_pref_value) { |
100 DVLOG(1) << "Found user pref value for " << pref_name; | 95 DVLOG(1) << "Found user pref value for " << pref_name; |
(...skipping 17 matching lines...) Expand all Loading... | |
118 } | 113 } |
119 | 114 |
120 // If the merge resulted in an updated value, inform the syncer. | 115 // If the merge resulted in an updated value, inform the syncer. |
121 if (!sync_value->Equals(new_value.get())) { | 116 if (!sync_value->Equals(new_value.get())) { |
122 syncer::SyncData sync_data; | 117 syncer::SyncData sync_data; |
123 if (!CreatePrefSyncData(pref_name, *new_value, &sync_data)) { | 118 if (!CreatePrefSyncData(pref_name, *new_value, &sync_data)) { |
124 LOG(ERROR) << "Failed to update preference."; | 119 LOG(ERROR) << "Failed to update preference."; |
125 return; | 120 return; |
126 } | 121 } |
127 | 122 |
128 std::string old_pref_name; | 123 sync_changes->push_back( |
129 if (client_ && | 124 syncer::SyncChange(FROM_HERE, |
130 client_->IsMigratedPreference(pref_name, &old_pref_name)) { | 125 syncer::SyncChange::ACTION_UPDATE, |
131 // This preference has been migrated from an old version that must be | 126 sync_data)); |
132 // kept in sync on older versions of Chrome. | |
133 if (preference.name() == old_pref_name) { | |
134 DCHECK(migrated_preference_list); | |
135 // If the name the syncer has is the old pre-migration value, then | |
136 // it's possible the new migrated preference name hasn't been synced | |
137 // yet. In that case the SyncChange should be an ACTION_ADD rather | |
138 // than an ACTION_UPDATE. Defer the decision of whether to sync with | |
139 // ACTION_ADD or ACTION_UPDATE until the migrated_preferences phase. | |
140 if (migrated_preference_list) | |
141 (*migrated_preference_list)[pref_name] = sync_data; | |
142 } else { | |
143 DCHECK_EQ(preference.name(), pref_name); | |
144 sync_changes->push_back( | |
145 syncer::SyncChange(FROM_HERE, | |
146 syncer::SyncChange::ACTION_UPDATE, | |
147 sync_data)); | |
148 } | |
149 | |
150 syncer::SyncData old_sync_data; | |
151 if (!CreatePrefSyncData(old_pref_name, *new_value, &old_sync_data)) { | |
152 LOG(ERROR) << "Failed to update preference."; | |
153 return; | |
154 } | |
155 if (migrated_preference_list) | |
156 (*migrated_preference_list)[old_pref_name] = old_sync_data; | |
157 } else { | |
158 sync_changes->push_back( | |
159 syncer::SyncChange(FROM_HERE, | |
160 syncer::SyncChange::ACTION_UPDATE, | |
161 sync_data)); | |
162 } | |
163 } | 127 } |
164 } else if (!sync_value->IsType(base::Value::TYPE_NULL)) { | 128 } else if (!sync_value->IsType(base::Value::TYPE_NULL)) { |
165 // Only a server value exists. Just set the local user value. | 129 // Only a server value exists. Just set the local user value. |
166 pref_service_->Set(pref_name.c_str(), *sync_value); | 130 pref_service_->Set(pref_name.c_str(), *sync_value); |
167 } else { | 131 } else { |
168 LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str(); | 132 LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str(); |
169 } | 133 } |
170 synced_preferences_.insert(preference.name()); | 134 synced_preferences_.insert(preference.name()); |
171 } else if (user_pref_value) { | 135 } else if (user_pref_value) { |
172 // The server does not know about this preference and should be added | 136 // The server does not know about this preference and should be added |
(...skipping 27 matching lines...) Expand all Loading... | |
200 DCHECK(!sync_processor_.get()); | 164 DCHECK(!sync_processor_.get()); |
201 DCHECK(sync_processor.get()); | 165 DCHECK(sync_processor.get()); |
202 DCHECK(sync_error_factory.get()); | 166 DCHECK(sync_error_factory.get()); |
203 syncer::SyncMergeResult merge_result(type); | 167 syncer::SyncMergeResult merge_result(type); |
204 sync_processor_ = sync_processor.Pass(); | 168 sync_processor_ = sync_processor.Pass(); |
205 sync_error_factory_ = sync_error_factory.Pass(); | 169 sync_error_factory_ = sync_error_factory.Pass(); |
206 | 170 |
207 syncer::SyncChangeList new_changes; | 171 syncer::SyncChangeList new_changes; |
208 std::set<std::string> remaining_preferences = registered_preferences_; | 172 std::set<std::string> remaining_preferences = registered_preferences_; |
209 | 173 |
210 // Maintains a list of old migrated preference names that we wish to sync. | |
211 // Keep track of these in a list such that when the preference iteration | |
212 // loops below are complete we can go back and determine whether | |
213 SyncDataMap migrated_preference_list; | |
214 | |
215 // Go through and check for all preferences we care about that sync already | 174 // Go through and check for all preferences we care about that sync already |
216 // knows about. | 175 // knows about. |
217 for (syncer::SyncDataList::const_iterator sync_iter = | 176 for (syncer::SyncDataList::const_iterator sync_iter = |
218 initial_sync_data.begin(); | 177 initial_sync_data.begin(); |
219 sync_iter != initial_sync_data.end(); | 178 sync_iter != initial_sync_data.end(); |
220 ++sync_iter) { | 179 ++sync_iter) { |
221 DCHECK_EQ(type_, sync_iter->GetDataType()); | 180 DCHECK_EQ(type_, sync_iter->GetDataType()); |
222 | 181 |
223 const sync_pb::PreferenceSpecifics& preference = GetSpecifics(*sync_iter); | 182 const sync_pb::PreferenceSpecifics& preference = GetSpecifics(*sync_iter); |
224 std::string sync_pref_name = preference.name(); | 183 std::string sync_pref_name = preference.name(); |
225 | 184 |
226 if (remaining_preferences.count(sync_pref_name) == 0) { | 185 if (remaining_preferences.count(sync_pref_name) == 0) { |
227 std::string new_pref_name; | 186 // We're not syncing this preference locally, ignore the sync data. |
228 if (client_ && | 187 // TODO(zea): Eventually we want to be able to have the syncable service |
229 client_->IsOldMigratedPreference(sync_pref_name, &new_pref_name)) { | 188 // reconstruct all sync data for its datatype (therefore having |
230 // This old pref name is not syncable locally anymore but we accept | 189 // GetAllSyncData be a complete representation). We should store this |
231 // changes from other Chrome installs of previous versions and migrate | 190 // data somewhere, even if we don't use it. |
232 // them to the new name. Note that we will be merging any differences | 191 continue; |
233 // between the new and old values and sync'ing them back. | |
234 sync_pref_name = new_pref_name; | |
235 } else { | |
236 // We're not syncing this preference locally, ignore the sync data. | |
237 // TODO(zea): Eventually we want to be able to have the syncable service | |
238 // reconstruct all sync data for its datatype (therefore having | |
239 // GetAllSyncData be a complete representation). We should store this | |
240 // data somewhere, even if we don't use it. | |
241 continue; | |
242 } | |
243 } else { | |
244 remaining_preferences.erase(sync_pref_name); | |
245 } | 192 } |
246 InitPrefAndAssociate(*sync_iter, sync_pref_name, &new_changes, | 193 |
247 &migrated_preference_list); | 194 remaining_preferences.erase(sync_pref_name); |
gab
2015/12/02 21:06:51
If I'm reading the old logic correctly, this shoul
sdefresne
2015/12/03 10:02:29
There is no else block now as I changed the code f
gab
2015/12/03 15:25:37
Ah, indeed, had missed that.
| |
195 InitPrefAndAssociate(*sync_iter, sync_pref_name, &new_changes); | |
248 } | 196 } |
249 | 197 |
250 // Go through and build sync data for any remaining preferences. | 198 // Go through and build sync data for any remaining preferences. |
251 for (std::set<std::string>::iterator pref_name_iter = | 199 for (std::set<std::string>::iterator pref_name_iter = |
252 remaining_preferences.begin(); | 200 remaining_preferences.begin(); |
253 pref_name_iter != remaining_preferences.end(); | 201 pref_name_iter != remaining_preferences.end(); |
254 ++pref_name_iter) { | 202 ++pref_name_iter) { |
255 InitPrefAndAssociate(syncer::SyncData(), *pref_name_iter, &new_changes, | 203 InitPrefAndAssociate(syncer::SyncData(), *pref_name_iter, &new_changes); |
256 &migrated_preference_list); | |
257 } | |
258 | |
259 // Now go over any migrated preference names and build sync data for them too. | |
260 for (SyncDataMap::const_iterator migrated_pref_iter = | |
261 migrated_preference_list.begin(); | |
262 migrated_pref_iter != migrated_preference_list.end(); | |
263 ++migrated_pref_iter) { | |
264 syncer::SyncChange::SyncChangeType change_type = | |
265 (synced_preferences_.count(migrated_pref_iter->first) == 0) ? | |
266 syncer::SyncChange::ACTION_ADD : | |
267 syncer::SyncChange::ACTION_UPDATE; | |
268 new_changes.push_back( | |
269 syncer::SyncChange(FROM_HERE, change_type, migrated_pref_iter->second)); | |
270 synced_preferences_.insert(migrated_pref_iter->first); | |
271 } | 204 } |
272 | 205 |
273 // Push updates to sync. | 206 // Push updates to sync. |
274 merge_result.set_error( | 207 merge_result.set_error( |
275 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | 208 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
276 if (merge_result.error().IsSet()) | 209 if (merge_result.error().IsSet()) |
277 return merge_result; | 210 return merge_result; |
278 | 211 |
279 models_associated_ = true; | 212 models_associated_ = true; |
280 pref_service_->OnIsSyncingChanged(); | 213 pref_service_->OnIsSyncingChanged(); |
281 return merge_result; | 214 return merge_result; |
282 } | 215 } |
283 | 216 |
284 void PrefModelAssociator::StopSyncing(syncer::ModelType type) { | 217 void PrefModelAssociator::StopSyncing(syncer::ModelType type) { |
285 DCHECK_EQ(type_, type); | 218 DCHECK_EQ(type_, type); |
286 models_associated_ = false; | 219 models_associated_ = false; |
287 sync_processor_.reset(); | 220 sync_processor_.reset(); |
288 sync_error_factory_.reset(); | 221 sync_error_factory_.reset(); |
289 pref_service_->OnIsSyncingChanged(); | 222 pref_service_->OnIsSyncingChanged(); |
290 } | 223 } |
291 | 224 |
292 scoped_ptr<base::Value> PrefModelAssociator::MergePreference( | 225 scoped_ptr<base::Value> PrefModelAssociator::MergePreference( |
293 const std::string& name, | 226 const std::string& name, |
294 const base::Value& local_value, | 227 const base::Value& local_value, |
295 const base::Value& server_value) { | 228 const base::Value& server_value) { |
296 // This function special cases preferences individually, so don't attempt | 229 // This function special cases preferences individually, so don't attempt |
297 // to merge for all migrated values. | 230 // to merge for all migrated values. |
298 if (client_) { | 231 if (client_) { |
299 std::string new_pref_name; | 232 std::string new_pref_name; |
300 DCHECK(!client_->IsOldMigratedPreference(name, &new_pref_name)); | |
301 if (client_->IsMergeableListPreference(name)) | 233 if (client_->IsMergeableListPreference(name)) |
302 return make_scoped_ptr(MergeListValues(local_value, server_value)); | 234 return make_scoped_ptr(MergeListValues(local_value, server_value)); |
303 if (client_->IsMergeableDictionaryPreference(name)) | 235 if (client_->IsMergeableDictionaryPreference(name)) |
304 return make_scoped_ptr(MergeDictionaryValues(local_value, server_value)); | 236 return make_scoped_ptr(MergeDictionaryValues(local_value, server_value)); |
305 } | 237 } |
306 | 238 |
307 // If this is not a specially handled preference, server wins. | 239 // If this is not a specially handled preference, server wins. |
308 return make_scoped_ptr(server_value.DeepCopy()); | 240 return make_scoped_ptr(server_value.DeepCopy()); |
309 } | 241 } |
310 | 242 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 | 371 |
440 const sync_pb::PreferenceSpecifics& pref_specifics = | 372 const sync_pb::PreferenceSpecifics& pref_specifics = |
441 GetSpecifics(iter->sync_data()); | 373 GetSpecifics(iter->sync_data()); |
442 | 374 |
443 std::string name = pref_specifics.name(); | 375 std::string name = pref_specifics.name(); |
444 // It is possible that we may receive a change to a preference we do not | 376 // It is possible that we may receive a change to a preference we do not |
445 // want to sync. For example if the user is syncing a Mac client and a | 377 // want to sync. For example if the user is syncing a Mac client and a |
446 // Windows client, the Windows client does not support | 378 // Windows client, the Windows client does not support |
447 // kConfirmToQuitEnabled. Ignore updates from these preferences. | 379 // kConfirmToQuitEnabled. Ignore updates from these preferences. |
448 std::string pref_name = pref_specifics.name(); | 380 std::string pref_name = pref_specifics.name(); |
449 std::string new_pref_name; | |
450 // We migrated this preference name, so do as if the name had not changed. | |
451 if (client_ && client_->IsOldMigratedPreference(name, &new_pref_name)) { | |
452 pref_name = new_pref_name; | |
453 } | |
454 | |
455 if (!IsPrefRegistered(pref_name.c_str())) | 381 if (!IsPrefRegistered(pref_name.c_str())) |
456 continue; | 382 continue; |
457 | 383 |
458 if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { | 384 if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { |
459 pref_service_->ClearPref(pref_name); | 385 pref_service_->ClearPref(pref_name); |
460 continue; | 386 continue; |
461 } | 387 } |
462 | 388 |
463 scoped_ptr<base::Value> value(ReadPreferenceSpecifics(pref_specifics)); | 389 scoped_ptr<base::Value> value(ReadPreferenceSpecifics(pref_specifics)); |
464 if (!value.get()) { | 390 if (!value.get()) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 } | 492 } |
567 | 493 |
568 base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | 494 base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
569 | 495 |
570 NotifySyncedPrefObservers(name, false /*from_sync*/); | 496 NotifySyncedPrefObservers(name, false /*from_sync*/); |
571 | 497 |
572 if (synced_preferences_.count(name) == 0) { | 498 if (synced_preferences_.count(name) == 0) { |
573 // Not in synced_preferences_ means no synced data. InitPrefAndAssociate(..) | 499 // Not in synced_preferences_ means no synced data. InitPrefAndAssociate(..) |
574 // will determine if we care about its data (e.g. if it has a default value | 500 // will determine if we care about its data (e.g. if it has a default value |
575 // and hasn't been changed yet we don't) and take care syncing any new data. | 501 // and hasn't been changed yet we don't) and take care syncing any new data. |
576 InitPrefAndAssociate(syncer::SyncData(), name, &changes, NULL); | 502 InitPrefAndAssociate(syncer::SyncData(), name, &changes); |
577 } else { | 503 } else { |
578 // We are already syncing this preference, just update it's sync node. | 504 // We are already syncing this preference, just update it's sync node. |
579 syncer::SyncData sync_data; | 505 syncer::SyncData sync_data; |
580 if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) { | 506 if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) { |
581 LOG(ERROR) << "Failed to update preference."; | 507 LOG(ERROR) << "Failed to update preference."; |
582 return; | 508 return; |
583 } | 509 } |
584 changes.push_back( | 510 changes.push_back( |
585 syncer::SyncChange(FROM_HERE, | 511 syncer::SyncChange(FROM_HERE, |
586 syncer::SyncChange::ACTION_UPDATE, | 512 syncer::SyncChange::ACTION_UPDATE, |
587 sync_data)); | 513 sync_data)); |
588 // This preference has been migrated from an old version that must be kept | |
589 // in sync on older versions of Chrome. | |
590 std::string old_pref_name; | |
591 if (client_ && client_->IsMigratedPreference(name, &old_pref_name)) { | |
592 if (!CreatePrefSyncData(old_pref_name, | |
593 *preference->GetValue(), | |
594 &sync_data)) { | |
595 LOG(ERROR) << "Failed to update preference."; | |
596 return; | |
597 } | |
598 | |
599 syncer::SyncChange::SyncChangeType change_type = | |
600 (synced_preferences_.count(old_pref_name) == 0) ? | |
601 syncer::SyncChange::ACTION_ADD : | |
602 syncer::SyncChange::ACTION_UPDATE; | |
603 changes.push_back( | |
604 syncer::SyncChange(FROM_HERE, change_type, sync_data)); | |
605 } | |
606 } | 514 } |
607 | 515 |
608 syncer::SyncError error = | 516 syncer::SyncError error = |
609 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 517 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
610 } | 518 } |
611 | 519 |
612 void PrefModelAssociator::SetPrefService(PrefServiceSyncable* pref_service) { | 520 void PrefModelAssociator::SetPrefService(PrefServiceSyncable* pref_service) { |
613 DCHECK(pref_service_ == NULL); | 521 DCHECK(pref_service_ == NULL); |
614 pref_service_ = pref_service; | 522 pref_service_ = pref_service; |
615 } | 523 } |
616 | 524 |
617 void PrefModelAssociator::NotifySyncedPrefObservers(const std::string& path, | 525 void PrefModelAssociator::NotifySyncedPrefObservers(const std::string& path, |
618 bool from_sync) const { | 526 bool from_sync) const { |
619 SyncedPrefObserverMap::const_iterator observer_iter = | 527 SyncedPrefObserverMap::const_iterator observer_iter = |
620 synced_pref_observers_.find(path); | 528 synced_pref_observers_.find(path); |
621 if (observer_iter == synced_pref_observers_.end()) | 529 if (observer_iter == synced_pref_observers_.end()) |
622 return; | 530 return; |
623 SyncedPrefObserverList* observers = observer_iter->second; | 531 SyncedPrefObserverList* observers = observer_iter->second; |
624 FOR_EACH_OBSERVER(SyncedPrefObserver, *observers, | 532 FOR_EACH_OBSERVER(SyncedPrefObserver, *observers, |
625 OnSyncedPrefChanged(path, from_sync)); | 533 OnSyncedPrefChanged(path, from_sync)); |
626 } | 534 } |
627 | 535 |
628 } // namespace syncable_prefs | 536 } // namespace syncable_prefs |
OLD | NEW |