[email protected] | ffbec69 | 2012-02-26 20:26:42 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 5 | #include "components/sync_preferences/pref_model_associator.h" |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 6 | |
jdoerrie | 89aa5721 | 2017-05-22 08:36:03 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | #include <iterator> |
Gyuyoung Kim | 8b084c0 | 2018-01-23 13:34:37 | [diff] [blame] | 9 | #include <memory> |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 10 | #include <utility> |
| 11 | |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 12 | #include "base/auto_reset.h" |
| 13 | #include "base/json/json_reader.h" |
[email protected] | ffbec69 | 2012-02-26 20:26:42 | [diff] [blame] | 14 | #include "base/json/json_string_value_serializer.h" |
[email protected] | c62dd9d | 2011-09-21 18:05:41 | [diff] [blame] | 15 | #include "base/location.h" |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 16 | #include "base/logging.h" |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 17 | #include "base/memory/ptr_util.h" |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 18 | #include "base/metrics/histogram_macros.h" |
Hwanseung Lee | 2e9a253 | 2018-06-19 06:22:28 | [diff] [blame] | 19 | #include "base/stl_util.h" |
[email protected] | e309f31 | 2013-06-07 21:50:08 | [diff] [blame] | 20 | #include "base/strings/utf_string_conversions.h" |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 21 | #include "base/values.h" |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 22 | #include "components/prefs/persistent_pref_store.h" |
brettw | f00b9b4 | 2016-02-01 22:11:38 | [diff] [blame] | 23 | #include "components/prefs/pref_service.h" |
skym | 7160384 | 2016-10-10 18:17:31 | [diff] [blame] | 24 | #include "components/sync/model/sync_change.h" |
| 25 | #include "components/sync/model/sync_error_factory.h" |
Max Bogue | fef332d | 2016-07-28 22:09:09 | [diff] [blame] | 26 | #include "components/sync/protocol/preference_specifics.pb.h" |
| 27 | #include "components/sync/protocol/sync.pb.h" |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 28 | #include "components/sync_preferences/pref_model_associator_client.h" |
| 29 | #include "components/sync_preferences/pref_service_syncable.h" |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 30 | #include "components/sync_preferences/synced_pref_observer.h" |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 31 | |
[email protected] | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 32 | using syncer::PREFERENCES; |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 33 | using syncer::PRIORITY_PREFERENCES; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 34 | |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 35 | namespace sync_preferences { |
sdefresne | 50c1e52 | 2015-09-18 09:47:51 | [diff] [blame] | 36 | |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 37 | namespace { |
| 38 | |
| 39 | const sync_pb::PreferenceSpecifics& GetSpecifics(const syncer::SyncData& pref) { |
| 40 | DCHECK(pref.GetDataType() == syncer::PREFERENCES || |
| 41 | pref.GetDataType() == syncer::PRIORITY_PREFERENCES); |
| 42 | if (pref.GetDataType() == syncer::PRIORITY_PREFERENCES) { |
| 43 | return pref.GetSpecifics().priority_preference().preference(); |
| 44 | } else { |
| 45 | return pref.GetSpecifics().preference(); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | sync_pb::PreferenceSpecifics* GetMutableSpecifics( |
| 50 | const syncer::ModelType type, |
| 51 | sync_pb::EntitySpecifics* specifics) { |
| 52 | if (type == syncer::PRIORITY_PREFERENCES) { |
| 53 | DCHECK(!specifics->has_preference()); |
| 54 | return specifics->mutable_priority_preference()->mutable_preference(); |
| 55 | } else { |
| 56 | DCHECK(!specifics->has_priority_preference()); |
| 57 | return specifics->mutable_preference(); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | } // namespace |
| 62 | |
sdefresne | 96bc5cc | 2015-09-15 15:47:54 | [diff] [blame] | 63 | PrefModelAssociator::PrefModelAssociator( |
| 64 | const PrefModelAssociatorClient* client, |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 65 | syncer::ModelType type, |
| 66 | UnknownUserPrefAccessor* accessor) |
| 67 | : pref_accessor_(accessor), type_(type), client_(client) { |
gab | febb8e8 | 2017-05-30 08:50:38 | [diff] [blame] | 68 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 69 | DCHECK(type_ == PREFERENCES || type_ == PRIORITY_PREFERENCES); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | PrefModelAssociator::~PrefModelAssociator() { |
gab | febb8e8 | 2017-05-30 08:50:38 | [diff] [blame] | 73 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
Ivan Kotenkov | 75b1c3a | 2017-10-24 14:47:24 | [diff] [blame] | 74 | pref_service_ = nullptr; |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 75 | |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 76 | synced_pref_observers_.clear(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 77 | } |
| 78 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 79 | void PrefModelAssociator::InitPrefAndAssociate( |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 80 | const syncer::SyncData& sync_pref, |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 81 | const std::string& pref_name, |
sdefresne | 39dc3a1f | 2015-12-03 15:06:17 | [diff] [blame] | 82 | syncer::SyncChangeList* sync_changes) { |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 83 | UnknownUserPrefAccessor::PreferenceState local_pref_state = |
Tim Schumann | 6787d06 | 2018-06-14 14:10:33 | [diff] [blame] | 84 | pref_accessor_->GetPreferenceState(type_, pref_name); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 85 | if (local_pref_state.registration_state == |
| 86 | UnknownUserPrefAccessor::RegistrationState::kUnknown || |
| 87 | local_pref_state.registration_state == |
| 88 | UnknownUserPrefAccessor::RegistrationState::kNotSyncable) { |
| 89 | // Only process syncable prefs and unknown prefs if whitelisted. |
| 90 | return; |
| 91 | } |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 92 | VLOG(1) << "Associating preference " << pref_name; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 93 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 94 | if (sync_pref.IsValid()) { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 95 | const sync_pb::PreferenceSpecifics& preference = GetSpecifics(sync_pref); |
sdefresne | 39dc3a1f | 2015-12-03 15:06:17 | [diff] [blame] | 96 | DCHECK(pref_name == preference.name()); |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 97 | base::JSONReader reader; |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 98 | std::unique_ptr<base::Value> sync_value( |
| 99 | reader.ReadToValue(preference.value())); |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 100 | if (!sync_value.get()) { |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 101 | LOG(ERROR) << "Failed to deserialize preference value: " |
| 102 | << reader.GetErrorMessage(); |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 103 | return; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 104 | } |
| 105 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 106 | if (local_pref_state.persisted_value) { |
[email protected] | 9c25503 | 2013-10-29 00:37:33 | [diff] [blame] | 107 | DVLOG(1) << "Found user pref value for " << pref_name; |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 108 | // We have both server and local values. Merge them. |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 109 | std::unique_ptr<base::Value> new_value(MergePreference( |
| 110 | pref_name, *local_pref_state.persisted_value, *sync_value)); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 111 | |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 112 | // Update the local preference based on what we got from the |
| 113 | // sync server. Note: this only updates the user value store, which is |
| 114 | // ignored if the preference is policy controlled. |
jdoerrie | f39c2a7 | 2017-11-22 10:39:32 | [diff] [blame] | 115 | if (new_value->is_none()) { |
[email protected] | ac1da2f | 2012-12-13 02:09:57 | [diff] [blame] | 116 | LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str(); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 117 | pref_accessor_->ClearPref(pref_name, local_pref_state); |
| 118 | } else if (!local_pref_state.persisted_value->Equals(new_value.get())) { |
| 119 | pref_accessor_->SetPref(pref_name, local_pref_state, *new_value); |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 120 | } |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 121 | |
| 122 | // If the merge resulted in an updated value, inform the syncer. |
| 123 | if (!sync_value->Equals(new_value.get())) { |
| 124 | syncer::SyncData sync_data; |
| 125 | if (!CreatePrefSyncData(pref_name, *new_value, &sync_data)) { |
| 126 | LOG(ERROR) << "Failed to update preference."; |
| 127 | return; |
| 128 | } |
[email protected] | 990ebf1 | 2013-10-19 10:33:21 | [diff] [blame] | 129 | |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 130 | sync_changes->push_back(syncer::SyncChange( |
| 131 | FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data)); |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 132 | } |
jdoerrie | f39c2a7 | 2017-11-22 10:39:32 | [diff] [blame] | 133 | } else if (!sync_value->is_none()) { |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 134 | // Only a server value exists. Just set the local user value. |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 135 | pref_accessor_->SetPref(pref_name, local_pref_state, *sync_value); |
[email protected] | ac1da2f | 2012-12-13 02:09:57 | [diff] [blame] | 136 | } else { |
| 137 | LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 138 | } |
[email protected] | 9c25503 | 2013-10-29 00:37:33 | [diff] [blame] | 139 | synced_preferences_.insert(preference.name()); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 140 | } else if (local_pref_state.persisted_value) { |
| 141 | DCHECK_EQ(local_pref_state.registration_state, |
| 142 | UnknownUserPrefAccessor::RegistrationState::kSyncable); |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 143 | // The server does not know about this preference and should be added |
| 144 | // to the syncer's database. |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 145 | syncer::SyncData sync_data; |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 146 | if (!CreatePrefSyncData(pref_name, *local_pref_state.persisted_value, |
| 147 | &sync_data)) { |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 148 | LOG(ERROR) << "Failed to update preference."; |
| 149 | return; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 150 | } |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 151 | sync_changes->push_back(syncer::SyncChange( |
| 152 | FROM_HERE, syncer::SyncChange::ACTION_ADD, sync_data)); |
[email protected] | 9c25503 | 2013-10-29 00:37:33 | [diff] [blame] | 153 | synced_preferences_.insert(pref_name); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 154 | } |
| 155 | |
[email protected] | 9c25503 | 2013-10-29 00:37:33 | [diff] [blame] | 156 | // Else this pref does not have a sync value but also does not have a user |
| 157 | // controlled value (either it's a default value or it's policy controlled, |
| 158 | // either way it's not interesting). We can ignore it. Once it gets changed, |
| 159 | // we'll send the new user controlled value to the syncer. |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 160 | } |
| 161 | |
lshang | 2cf5c57 | 2016-07-15 01:36:32 | [diff] [blame] | 162 | void PrefModelAssociator::RegisterMergeDataFinishedCallback( |
| 163 | const base::Closure& callback) { |
| 164 | if (!models_associated_) |
| 165 | callback_list_.push_back(callback); |
| 166 | else |
| 167 | callback.Run(); |
| 168 | } |
| 169 | |
[email protected] | 3f98fd9 | 2012-11-17 15:54:29 | [diff] [blame] | 170 | syncer::SyncMergeResult PrefModelAssociator::MergeDataAndStartSyncing( |
[email protected] | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 171 | syncer::ModelType type, |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 172 | const syncer::SyncDataList& initial_sync_data, |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 173 | std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 174 | std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 175 | DCHECK_EQ(type_, type); |
gab | febb8e8 | 2017-05-30 08:50:38 | [diff] [blame] | 176 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 361d37f6 | 2011-11-22 10:37:02 | [diff] [blame] | 177 | DCHECK(pref_service_); |
[email protected] | 0677c695 | 2012-03-23 21:59:00 | [diff] [blame] | 178 | DCHECK(!sync_processor_.get()); |
| 179 | DCHECK(sync_processor.get()); |
[email protected] | 5d36e05 | 2012-04-20 20:12:28 | [diff] [blame] | 180 | DCHECK(sync_error_factory.get()); |
[email protected] | 3f98fd9 | 2012-11-17 15:54:29 | [diff] [blame] | 181 | syncer::SyncMergeResult merge_result(type); |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 182 | sync_processor_ = std::move(sync_processor); |
| 183 | sync_error_factory_ = std::move(sync_error_factory); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 184 | |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 185 | syncer::SyncChangeList new_changes; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 186 | std::set<std::string> remaining_preferences = registered_preferences_; |
| 187 | |
| 188 | // Go through and check for all preferences we care about that sync already |
| 189 | // knows about. |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 190 | for (syncer::SyncDataList::const_iterator sync_iter = |
[email protected] | cb02f61 | 2012-06-27 03:15:50 | [diff] [blame] | 191 | initial_sync_data.begin(); |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 192 | sync_iter != initial_sync_data.end(); ++sync_iter) { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 193 | DCHECK_EQ(type_, sync_iter->GetDataType()); |
| 194 | |
| 195 | const sync_pb::PreferenceSpecifics& preference = GetSpecifics(*sync_iter); |
[email protected] | 990ebf1 | 2013-10-19 10:33:21 | [diff] [blame] | 196 | std::string sync_pref_name = preference.name(); |
sdefresne | 39dc3a1f | 2015-12-03 15:06:17 | [diff] [blame] | 197 | remaining_preferences.erase(sync_pref_name); |
| 198 | InitPrefAndAssociate(*sync_iter, sync_pref_name, &new_changes); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 199 | } |
| 200 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 201 | // Go through and build sync data for any remaining preferences. |
| 202 | for (std::set<std::string>::iterator pref_name_iter = |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 203 | remaining_preferences.begin(); |
| 204 | pref_name_iter != remaining_preferences.end(); ++pref_name_iter) { |
sdefresne | 39dc3a1f | 2015-12-03 15:06:17 | [diff] [blame] | 205 | InitPrefAndAssociate(syncer::SyncData(), *pref_name_iter, &new_changes); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 206 | } |
| 207 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 208 | UMA_HISTOGRAM_COUNTS_1000("Sync.Preferences.SyncingUnknownPrefs", |
| 209 | pref_accessor_->GetNumberOfSyncingUnknownPrefs()); |
| 210 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 211 | // Push updates to sync. |
[email protected] | 3f98fd9 | 2012-11-17 15:54:29 | [diff] [blame] | 212 | merge_result.set_error( |
| 213 | sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
| 214 | if (merge_result.error().IsSet()) |
| 215 | return merge_result; |
[email protected] | de7d78c7 | 2011-07-26 23:41:50 | [diff] [blame] | 216 | |
lshang | 2cf5c57 | 2016-07-15 01:36:32 | [diff] [blame] | 217 | for (const auto& callback : callback_list_) |
| 218 | callback.Run(); |
| 219 | callback_list_.clear(); |
| 220 | |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 221 | models_associated_ = true; |
[email protected] | 33db532 | 2012-10-26 23:14:36 | [diff] [blame] | 222 | pref_service_->OnIsSyncingChanged(); |
[email protected] | 3f98fd9 | 2012-11-17 15:54:29 | [diff] [blame] | 223 | return merge_result; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 224 | } |
| 225 | |
[email protected] | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 226 | void PrefModelAssociator::StopSyncing(syncer::ModelType type) { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 227 | DCHECK_EQ(type_, type); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 228 | models_associated_ = false; |
[email protected] | 0677c695 | 2012-03-23 21:59:00 | [diff] [blame] | 229 | sync_processor_.reset(); |
[email protected] | 5d36e05 | 2012-04-20 20:12:28 | [diff] [blame] | 230 | sync_error_factory_.reset(); |
[email protected] | 33db532 | 2012-10-26 23:14:36 | [diff] [blame] | 231 | pref_service_->OnIsSyncingChanged(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 232 | } |
| 233 | |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 234 | std::unique_ptr<base::Value> PrefModelAssociator::MergePreference( |
[email protected] | fa0dde7d | 2012-11-20 00:52:43 | [diff] [blame] | 235 | const std::string& name, |
[email protected] | cb1078de | 2013-12-23 20:04:22 | [diff] [blame] | 236 | const base::Value& local_value, |
| 237 | const base::Value& server_value) { |
[email protected] | 990ebf1 | 2013-10-19 10:33:21 | [diff] [blame] | 238 | // This function special cases preferences individually, so don't attempt |
| 239 | // to merge for all migrated values. |
sdefresne | 96bc5cc | 2015-09-15 15:47:54 | [diff] [blame] | 240 | if (client_) { |
| 241 | std::string new_pref_name; |
sdefresne | 96bc5cc | 2015-09-15 15:47:54 | [diff] [blame] | 242 | if (client_->IsMergeableListPreference(name)) |
jdoerrie | 89aa5721 | 2017-05-22 08:36:03 | [diff] [blame] | 243 | return MergeListValues(local_value, server_value); |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 244 | if (client_->IsMergeableDictionaryPreference(name)) { |
Gyuyoung Kim | 8b084c0 | 2018-01-23 13:34:37 | [diff] [blame] | 245 | return std::make_unique<base::Value>( |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 246 | MergeDictionaryValues(local_value, server_value)); |
| 247 | } |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 248 | } |
| 249 | |
| 250 | // If this is not a specially handled preference, server wins. |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 251 | return base::WrapUnique(server_value.DeepCopy()); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 252 | } |
| 253 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 254 | bool PrefModelAssociator::CreatePrefSyncData( |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 255 | const std::string& name, |
[email protected] | cb1078de | 2013-12-23 20:04:22 | [diff] [blame] | 256 | const base::Value& value, |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 257 | syncer::SyncData* sync_data) const { |
jdoerrie | f39c2a7 | 2017-11-22 10:39:32 | [diff] [blame] | 258 | if (value.is_none()) { |
[email protected] | ac1da2f | 2012-12-13 02:09:57 | [diff] [blame] | 259 | LOG(ERROR) << "Attempting to sync a null pref value for " << name; |
| 260 | return false; |
| 261 | } |
| 262 | |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 263 | std::string serialized; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 264 | // TODO(zea): consider JSONWriter::Write since you don't have to check |
| 265 | // failures to deserialize. |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 266 | JSONStringValueSerializer json(&serialized); |
| 267 | if (!json.Serialize(value)) { |
| 268 | LOG(ERROR) << "Failed to serialize preference value."; |
| 269 | return false; |
| 270 | } |
| 271 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 272 | sync_pb::EntitySpecifics specifics; |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 273 | sync_pb::PreferenceSpecifics* pref_specifics = |
| 274 | GetMutableSpecifics(type_, &specifics); |
| 275 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 276 | pref_specifics->set_name(name); |
| 277 | pref_specifics->set_value(serialized); |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 278 | *sync_data = syncer::SyncData::CreateLocalData(name, name, specifics); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 279 | return true; |
| 280 | } |
| 281 | |
jdoerrie | 89aa5721 | 2017-05-22 08:36:03 | [diff] [blame] | 282 | std::unique_ptr<base::Value> PrefModelAssociator::MergeListValues( |
| 283 | const base::Value& from_value, |
| 284 | const base::Value& to_value) { |
jdoerrie | f39c2a7 | 2017-11-22 10:39:32 | [diff] [blame] | 285 | if (from_value.is_none()) |
Lei Zhang | 4a9c356 | 2017-10-26 19:46:44 | [diff] [blame] | 286 | return base::Value::ToUniquePtrValue(to_value.Clone()); |
jdoerrie | f39c2a7 | 2017-11-22 10:39:32 | [diff] [blame] | 287 | if (to_value.is_none()) |
Lei Zhang | 4a9c356 | 2017-10-26 19:46:44 | [diff] [blame] | 288 | return base::Value::ToUniquePtrValue(from_value.Clone()); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 289 | |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 290 | DCHECK(from_value.type() == base::Value::Type::LIST); |
| 291 | DCHECK(to_value.type() == base::Value::Type::LIST); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 292 | |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 293 | base::Value result = to_value.Clone(); |
| 294 | base::Value::ListStorage& list = result.GetList(); |
| 295 | for (const auto& value : from_value.GetList()) { |
Hwanseung Lee | 2e9a253 | 2018-06-19 06:22:28 | [diff] [blame] | 296 | if (!base::ContainsValue(list, value)) |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 297 | list.emplace_back(value.Clone()); |
| 298 | } |
| 299 | |
Lei Zhang | 4a9c356 | 2017-10-26 19:46:44 | [diff] [blame] | 300 | return base::Value::ToUniquePtrValue(std::move(result)); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 301 | } |
| 302 | |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 303 | base::Value PrefModelAssociator::MergeDictionaryValues( |
[email protected] | cb1078de | 2013-12-23 20:04:22 | [diff] [blame] | 304 | const base::Value& from_value, |
| 305 | const base::Value& to_value) { |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 306 | if (from_value.is_none()) |
| 307 | return to_value.Clone(); |
| 308 | if (to_value.is_none()) |
| 309 | return from_value.Clone(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 310 | |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 311 | DCHECK(from_value.is_dict()); |
| 312 | DCHECK(to_value.is_dict()); |
| 313 | base::Value result = to_value.Clone(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 314 | |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 315 | for (const auto& it : from_value.DictItems()) { |
| 316 | const base::Value* from_key_value = &it.second; |
| 317 | base::Value* to_key_value = result.FindKey(it.first); |
| 318 | if (to_key_value) { |
| 319 | if (from_key_value->is_dict() && to_key_value->is_dict()) { |
| 320 | *to_key_value = MergeDictionaryValues(*from_key_value, *to_key_value); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 321 | } |
| 322 | // Note that for all other types we want to preserve the "to" |
| 323 | // values so we do nothing here. |
| 324 | } else { |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 325 | result.SetKey(it.first, from_key_value->Clone()); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 326 | } |
| 327 | } |
jdoerrie | cc9f573 | 2017-08-23 14:12:30 | [diff] [blame] | 328 | return result; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 329 | } |
| 330 | |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 331 | syncer::SyncDataList PrefModelAssociator::GetAllSyncData( |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 332 | syncer::ModelType type) const { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 333 | DCHECK_EQ(type_, type); |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 334 | syncer::SyncDataList current_data; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 335 | for (PreferenceSet::const_iterator iter = synced_preferences_.begin(); |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 336 | iter != synced_preferences_.end(); ++iter) { |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 337 | std::string name = *iter; |
Tim Schumann | 6787d06 | 2018-06-14 14:10:33 | [diff] [blame] | 338 | if (pref_accessor_->GetPreferenceState(type_, name).registration_state != |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 339 | UnknownUserPrefAccessor::RegistrationState::kSyncable) { |
| 340 | continue; |
| 341 | } |
iceman | 4179f17c | 2017-03-29 19:50:09 | [diff] [blame] | 342 | const PrefService::Preference* pref = pref_service_->FindPreference(name); |
[email protected] | 7ff7c32 | 2011-06-22 20:28:18 | [diff] [blame] | 343 | DCHECK(pref); |
[email protected] | 7640df1 | 2011-06-20 21:51:46 | [diff] [blame] | 344 | if (!pref->IsUserControlled() || pref->IsDefaultValue()) |
| 345 | continue; // This is not data we care about. |
| 346 | // TODO(zea): plumb a way to read the user controlled value. |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 347 | syncer::SyncData sync_data; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 348 | if (!CreatePrefSyncData(name, *pref->GetValue(), &sync_data)) |
| 349 | continue; |
| 350 | current_data.push_back(sync_data); |
| 351 | } |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 352 | return current_data; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 353 | } |
| 354 | |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 355 | syncer::SyncError PrefModelAssociator::ProcessSyncChanges( |
Brett Wilson | 1c99002 | 2017-09-12 20:11:15 | [diff] [blame] | 356 | const base::Location& from_here, |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 357 | const syncer::SyncChangeList& change_list) { |
[email protected] | de7d78c7 | 2011-07-26 23:41:50 | [diff] [blame] | 358 | if (!models_associated_) { |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 359 | syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
| 360 | "Models not yet associated.", PREFERENCES); |
[email protected] | de7d78c7 | 2011-07-26 23:41:50 | [diff] [blame] | 361 | return error; |
| 362 | } |
[email protected] | 997ec9f | 2012-11-21 04:44:14 | [diff] [blame] | 363 | base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 364 | syncer::SyncChangeList::const_iterator iter; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 365 | for (iter = change_list.begin(); iter != change_list.end(); ++iter) { |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 366 | DCHECK_EQ(type_, iter->sync_data().GetDataType()); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 367 | |
[email protected] | 43fe640e | 2013-03-27 22:18:55 | [diff] [blame] | 368 | const sync_pb::PreferenceSpecifics& pref_specifics = |
| 369 | GetSpecifics(iter->sync_data()); |
| 370 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 371 | UnknownUserPrefAccessor::PreferenceState local_pref_state = |
Tim Schumann | 6787d06 | 2018-06-14 14:10:33 | [diff] [blame] | 372 | pref_accessor_->GetPreferenceState(type_, pref_specifics.name()); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 373 | if (local_pref_state.registration_state == |
| 374 | UnknownUserPrefAccessor::RegistrationState::kUnknown) { |
| 375 | // It is possible that we may receive a change to a preference we do not |
| 376 | // want to sync. For example if the user is syncing a Mac client and a |
| 377 | // Windows client, the Windows client does not support |
| 378 | // kConfirmToQuitEnabled. Ignore updates from these preferences. |
| 379 | // We only sync such prefs if they are whitelisted. |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 380 | continue; |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 381 | } |
| 382 | if (local_pref_state.registration_state == |
| 383 | UnknownUserPrefAccessor::RegistrationState::kNotSyncable) { |
| 384 | // Don't process remote changes for prefs this client doesn't want synced. |
| 385 | continue; |
| 386 | } |
[email protected] | c3f5a25 | 2014-08-12 19:28:26 | [diff] [blame] | 387 | if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 388 | pref_accessor_->ClearPref(pref_specifics.name(), local_pref_state); |
[email protected] | c3f5a25 | 2014-08-12 19:28:26 | [diff] [blame] | 389 | continue; |
| 390 | } |
| 391 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 392 | std::unique_ptr<base::Value> new_value( |
| 393 | ReadPreferenceSpecifics(pref_specifics)); |
| 394 | if (!new_value.get()) { |
[email protected] | c3f5a25 | 2014-08-12 19:28:26 | [diff] [blame] | 395 | // Skip values we can't deserialize. |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 396 | // TODO(zea): consider taking some further action such as erasing the |
| 397 | // bad data. |
[email protected] | c3f5a25 | 2014-08-12 19:28:26 | [diff] [blame] | 398 | continue; |
| 399 | } |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 400 | |
[email protected] | 7640df1 | 2011-06-20 21:51:46 | [diff] [blame] | 401 | // This will only modify the user controlled value store, which takes |
| 402 | // priority over the default value but is ignored if the preference is |
| 403 | // policy controlled. |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 404 | pref_accessor_->SetPref(pref_specifics.name(), local_pref_state, |
| 405 | *new_value); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 406 | |
sdefresne | 96bc5cc | 2015-09-15 15:47:54 | [diff] [blame] | 407 | NotifySyncedPrefObservers(pref_specifics.name(), true /*from_sync*/); |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 408 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 409 | // Keep track of any newly synced preferences. This can happen if a |
| 410 | // preference was late registered or remotely added (ACTION_ADD). |
| 411 | synced_preferences_.insert(pref_specifics.name()); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 412 | } |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 413 | return syncer::SyncError(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 414 | } |
| 415 | |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 416 | // static |
[email protected] | cb1078de | 2013-12-23 20:04:22 | [diff] [blame] | 417 | base::Value* PrefModelAssociator::ReadPreferenceSpecifics( |
[email protected] | c3f5a25 | 2014-08-12 19:28:26 | [diff] [blame] | 418 | const sync_pb::PreferenceSpecifics& preference) { |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 419 | base::JSONReader reader; |
danakj | 4d55af59c | 2016-04-22 22:42:02 | [diff] [blame] | 420 | std::unique_ptr<base::Value> value(reader.ReadToValue(preference.value())); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 421 | if (!value.get()) { |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 422 | std::string err = |
| 423 | "Failed to deserialize preference value: " + reader.GetErrorMessage(); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 424 | LOG(ERROR) << err; |
Ivan Kotenkov | 75b1c3a | 2017-10-24 14:47:24 | [diff] [blame] | 425 | return nullptr; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 426 | } |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 427 | return value.release(); |
| 428 | } |
| 429 | |
[email protected] | f3ca909 | 2013-05-26 02:25:15 | [diff] [blame] | 430 | bool PrefModelAssociator::IsPrefSynced(const std::string& name) const { |
| 431 | return synced_preferences_.find(name) != synced_preferences_.end(); |
| 432 | } |
| 433 | |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 434 | void PrefModelAssociator::AddSyncedPrefObserver(const std::string& name, |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 435 | SyncedPrefObserver* observer) { |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 436 | std::unique_ptr<base::ObserverList<SyncedPrefObserver>>& observers = |
avi | 8255475 | 2016-09-23 17:48:50 | [diff] [blame] | 437 | synced_pref_observers_[name]; |
| 438 | if (!observers) |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 439 | observers = std::make_unique<base::ObserverList<SyncedPrefObserver>>(); |
avi | 8255475 | 2016-09-23 17:48:50 | [diff] [blame] | 440 | |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 441 | observers->AddObserver(observer); |
| 442 | } |
| 443 | |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 444 | void PrefModelAssociator::RemoveSyncedPrefObserver( |
| 445 | const std::string& name, |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 446 | SyncedPrefObserver* observer) { |
avi | 8255475 | 2016-09-23 17:48:50 | [diff] [blame] | 447 | auto observer_iter = synced_pref_observers_.find(name); |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 448 | if (observer_iter == synced_pref_observers_.end()) |
| 449 | return; |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 450 | observer_iter->second->RemoveObserver(observer); |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 451 | } |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 452 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 453 | void PrefModelAssociator::RegisterPref(const std::string& name) { |
| 454 | DCHECK(!registered_preferences_.count(name)); |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 455 | registered_preferences_.insert(name); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 456 | |
| 457 | // This pref might be registered after sync started. Make sure data in the |
| 458 | // local store matches the registered type. |
| 459 | // If this results in a modification of the local pref store, we don't want |
| 460 | // to tell ChromeSync about these -- it's a local anomaly, |
| 461 | base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
| 462 | pref_accessor_->EnforceRegisteredTypeInStore(name); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 463 | } |
| 464 | |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 465 | bool PrefModelAssociator::IsPrefRegistered(const std::string& name) const { |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 466 | return registered_preferences_.count(name) > 0; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 467 | } |
| 468 | |
| 469 | void PrefModelAssociator::ProcessPrefChange(const std::string& name) { |
| 470 | if (processing_syncer_changes_) |
| 471 | return; // These are changes originating from us, ignore. |
| 472 | |
| 473 | // We only process changes if we've already associated models. |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 474 | // This also filters out local changes during the initial merge. |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 475 | if (!models_associated_) |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 476 | return; |
| 477 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 478 | // From now on, this method does not have to deal with lazily registered |
| 479 | // prefs, as local changes can only happen after they were registered. |
| 480 | |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 481 | const PrefService::Preference* preference = |
iceman | 4179f17c | 2017-03-29 19:50:09 | [diff] [blame] | 482 | pref_service_->FindPreference(name); |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 483 | // TODO(tschumann): When can this ever happen? Should this be a DCHECK? |
[email protected] | 7ff7c32 | 2011-06-22 20:28:18 | [diff] [blame] | 484 | if (!preference) |
| 485 | return; |
| 486 | |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 487 | if (!IsPrefRegistered(name)) { |
| 488 | // We are not syncing this preference -- this also filters out synced |
| 489 | // preferences of the wrong type (priority preference are handled by a |
| 490 | // separate associator). |
| 491 | return; |
| 492 | } |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 493 | |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 494 | syncer::SyncChangeList changes; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 495 | |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 496 | if (!preference->IsUserModifiable()) { |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 497 | // If the preference is no longer user modifiable, it must now be |
| 498 | // controlled by policy, whose values we do not sync. Just return. If the |
| 499 | // preference stops being controlled by policy, it will revert back to the |
| 500 | // user value (which we continue to update with sync changes). |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 501 | return; |
| 502 | } |
| 503 | |
[email protected] | 997ec9f | 2012-11-21 04:44:14 | [diff] [blame] | 504 | base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 505 | |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 506 | NotifySyncedPrefObservers(name, false /*from_sync*/); |
| 507 | |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 508 | if (synced_preferences_.count(name) == 0) { |
Tim Schumann | 13ef1e8 | 2018-05-30 01:37:15 | [diff] [blame] | 509 | // Not in synced_preferences_ means no synced data. |
| 510 | // InitPrefAndAssociate(..) will determine if we care about its data (e.g. |
| 511 | // if it has a default value and hasn't been changed yet we don't) and |
| 512 | // take care syncing any new data. |
sdefresne | 39dc3a1f | 2015-12-03 15:06:17 | [diff] [blame] | 513 | InitPrefAndAssociate(syncer::SyncData(), name, &changes); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 514 | } else { |
[email protected] | 7640df1 | 2011-06-20 21:51:46 | [diff] [blame] | 515 | // We are already syncing this preference, just update it's sync node. |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 516 | syncer::SyncData sync_data; |
[email protected] | 52c78823 | 2011-05-23 22:51:33 | [diff] [blame] | 517 | if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) { |
| 518 | LOG(ERROR) << "Failed to update preference."; |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 519 | return; |
| 520 | } |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 521 | changes.push_back(syncer::SyncChange( |
| 522 | FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data)); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 523 | } |
[email protected] | de7d78c7 | 2011-07-26 23:41:50 | [diff] [blame] | 524 | |
[email protected] | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 525 | syncer::SyncError error = |
[email protected] | de7d78c7 | 2011-07-26 23:41:50 | [diff] [blame] | 526 | sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
[email protected] | d36f941b | 2011-05-09 06:19:16 | [diff] [blame] | 527 | } |
[email protected] | 361d37f6 | 2011-11-22 10:37:02 | [diff] [blame] | 528 | |
[email protected] | 5b19952 | 2012-12-22 17:24:44 | [diff] [blame] | 529 | void PrefModelAssociator::SetPrefService(PrefServiceSyncable* pref_service) { |
Ivan Kotenkov | 75b1c3a | 2017-10-24 14:47:24 | [diff] [blame] | 530 | DCHECK(pref_service_ == nullptr); |
[email protected] | 361d37f6 | 2011-11-22 10:37:02 | [diff] [blame] | 531 | pref_service_ = pref_service; |
| 532 | } |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 533 | |
| 534 | void PrefModelAssociator::NotifySyncedPrefObservers(const std::string& path, |
| 535 | bool from_sync) const { |
avi | 8255475 | 2016-09-23 17:48:50 | [diff] [blame] | 536 | auto observer_iter = synced_pref_observers_.find(path); |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 537 | if (observer_iter == synced_pref_observers_.end()) |
| 538 | return; |
Tim Schumann | 978e750 | 2018-05-07 13:46:52 | [diff] [blame] | 539 | for (auto& observer : *observer_iter->second) |
ericwilligers | ff2af33 | 2016-10-19 00:16:50 | [diff] [blame] | 540 | observer.OnSyncedPrefChanged(path, from_sync); |
[email protected] | 0ebc403 | 2013-08-10 07:07:11 | [diff] [blame] | 541 | } |
sdefresne | 50c1e52 | 2015-09-18 09:47:51 | [diff] [blame] | 542 | |
maxbogue | ea16ff41 | 2016-10-28 16:35:29 | [diff] [blame] | 543 | } // namespace sync_preferences |