Fix handling of non-user controlled syncable preferences.
We now always update the pref user store with the sync data. Once a preference
stops being policy controlled, it will automatically pick up either the most
recent sync data or the previous user value.
BUG=86487
TEST=unit_tests --gtest_filter="*ProfileSyncServicePreference*"
Review URL: http://codereview.chromium.org/7205010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89738 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/prefs/pref_model_associator.cc b/chrome/browser/prefs/pref_model_associator.cc
index e6f55c9..682569ae 100644
--- a/chrome/browser/prefs/pref_model_associator.cc
+++ b/chrome/browser/prefs/pref_model_associator.cc
@@ -47,13 +47,6 @@
const PrefService::Preference* pref =
pref_service_->FindPreference(pref_name.c_str());
VLOG(1) << "Associating preference " << pref_name;
- if (!pref->IsUserModifiable()) {
- // This preference is controlled by policy. We don't need sync it, but if
- // there is sync data we want to track it for possible future use.
- if (sync_pref.IsValid())
- untracked_pref_sync_data_[pref_name] = sync_pref;
- return;
- }
base::JSONReader reader;
if (sync_pref.IsValid()) {
@@ -75,7 +68,8 @@
scoped_ptr<Value> new_value(MergePreference(*pref, *value));
// Update the local preference based on what we got from the
- // sync server.
+ // sync server. Note: this only updates the user value store, which is
+ // ignored if the preference is policy controlled.
if (new_value->IsType(Value::TYPE_NULL)) {
pref_service_->ClearPref(pref_name.c_str());
} else if (!new_value->IsType(pref->GetType())) {
@@ -107,8 +101,10 @@
}
sync_changes->push_back(SyncChange(SyncChange::ACTION_ADD, sync_data));
} else {
- // This pref has a default value, we can ignore it. Once it gets changed,
- // we'll send the new custom value to the syncer.
+ // This pref does not have a sync value but also does not have a user
+ // controlled value (either it's a default value or it's policy controlled,
+ // either way it's not interesting). We can ignore it. Once it gets changed,
+ // we'll send the new user controlled value to the syncer.
return;
}
@@ -169,7 +165,6 @@
DCHECK_EQ(type, PREFERENCES);
models_associated_ = false;
sync_processor_ = NULL;
- untracked_pref_sync_data_.clear();
}
Value* PrefModelAssociator::MergePreference(
@@ -297,16 +292,14 @@
std::string name = *iter;
const PrefService::Preference* pref =
pref_service_->FindPreference(name.c_str());
+ if (!pref->IsUserControlled() || pref->IsDefaultValue())
+ continue; // This is not data we care about.
+ // TODO(zea): plumb a way to read the user controlled value.
SyncData sync_data;
if (!CreatePrefSyncData(name, *pref->GetValue(), &sync_data))
continue;
current_data.push_back(sync_data);
}
- for (SyncDataMap::const_iterator iter = untracked_pref_sync_data_.begin();
- iter != untracked_pref_sync_data_.end();
- ++iter) {
- current_data.push_back(iter->second);
- }
return current_data;
}
@@ -350,16 +343,13 @@
const PrefService::Preference* pref =
pref_service_->FindPreference(pref_name);
DCHECK(pref);
- if (!pref->IsUserModifiable()) {
- // This preference is controlled by policy, ignore for now, but keep
- // the data around for possible later use.
- untracked_pref_sync_data_[name] = iter->sync_data();
- continue;
- }
+ // This will only modify the user controlled value store, which takes
+ // priority over the default value but is ignored if the preference is
+ // policy controlled.
pref_service_->Set(pref_name, *value);
- // If this is a newly added node, associate.
+ // Keep track of any newly synced preferences.
if (iter->change_type() == SyncChange::ACTION_ADD) {
synced_preferences_.insert(name);
}
@@ -387,10 +377,6 @@
return registered_preferences_;
}
-std::set<std::string> PrefModelAssociator::synced_preferences() const {
- return synced_preferences_;
-}
-
void PrefModelAssociator::RegisterPref(const char* name) {
DCHECK(!models_associated_ && registered_preferences_.count(name) == 0);
registered_preferences_.insert(name);
@@ -416,39 +402,23 @@
SyncChangeList changes;
if (!preference->IsUserModifiable()) {
- // If the preference is not currently user modifiable, back up the
- // previously synced value and remove it from our list of synced prefs.
- if (synced_preferences_.count(name) > 0) {
- synced_preferences_.erase(name);
- SyncData sync_data;
- if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) {
- LOG(ERROR) << "Failed to update preference.";
- return;
- }
- untracked_pref_sync_data_[name] = sync_data;
- }
+ // If the preference is no longer user modifiable, it must now be controlled
+ // by policy, whose values we do not sync. Just return. If the preference
+ // stops being controlled by policy, it will revert back to the user value
+ // (which we continue to update with sync changes).
return;
}
AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
if (synced_preferences_.count(name) == 0) {
- // This is a preference that changed locally but we were not syncing. This
- // happens when a preference was previously not user modifiable but now is,
- // or if it had a default value but the user set a custom one. We now care
- // about the preference and must inform the syncer, as well as update our
- // own internal tracking.
- if (untracked_pref_sync_data_.count(name) > 0) {
- // We have sync data for this preference, merge it (this only happens
- // when we went from policy-controlled to user controlled. Default values
- // are always overwritten by syncer values).
- InitPrefAndAssociate(untracked_pref_sync_data_[name], name, &changes);
- untracked_pref_sync_data_.erase(name);
- } else {
- InitPrefAndAssociate(SyncData(), name, &changes);
- }
+ DCHECK(preference->IsUserControlled());
+ // This preference was previously not user controlled and there was no sync
+ // data, but is now user controlled. We must associate it and create a sync
+ // node for it.
+ InitPrefAndAssociate(SyncData(), name, &changes);
} else {
- // We're already syncing this preference, we just need to update the data.
+ // We are already syncing this preference, just update it's sync node.
SyncData sync_data;
if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) {
LOG(ERROR) << "Failed to update preference.";