| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/sync/glue/preference_change_processor.h" | 5 #include "chrome/browser/sync/glue/preference_change_processor.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/auto_reset.h" |
| 10 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 11 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/browser/chrome_thread.h" | 13 #include "chrome/browser/chrome_thread.h" |
| 13 #include "chrome/browser/profile.h" | 14 #include "chrome/browser/profile.h" |
| 14 #include "chrome/browser/sync/glue/preference_model_associator.h" | 15 #include "chrome/browser/sync/glue/preference_model_associator.h" |
| 15 #include "chrome/browser/sync/profile_sync_service.h" | 16 #include "chrome/browser/sync/profile_sync_service.h" |
| 16 #include "chrome/browser/sync/protocol/preference_specifics.pb.h" | 17 #include "chrome/browser/sync/protocol/preference_specifics.pb.h" |
| 17 #include "chrome/common/json_value_serializer.h" | 18 #include "chrome/common/json_value_serializer.h" |
| 18 #include "chrome/common/notification_service.h" | 19 #include "chrome/common/notification_service.h" |
| 19 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 20 | 21 |
| 21 namespace browser_sync { | 22 namespace browser_sync { |
| 22 | 23 |
| 23 PreferenceChangeProcessor::PreferenceChangeProcessor( | 24 PreferenceChangeProcessor::PreferenceChangeProcessor( |
| 24 PreferenceModelAssociator* model_associator, | 25 PreferenceModelAssociator* model_associator, |
| 25 UnrecoverableErrorHandler* error_handler) | 26 UnrecoverableErrorHandler* error_handler) |
| 26 : ChangeProcessor(error_handler), | 27 : ChangeProcessor(error_handler), |
| 27 pref_service_(NULL), | 28 pref_service_(NULL), |
| 28 model_associator_(model_associator) { | 29 model_associator_(model_associator), |
| 30 processing_pref_change_(false) { |
| 29 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 31 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 30 DCHECK(model_associator); | 32 DCHECK(model_associator); |
| 31 DCHECK(error_handler); | 33 DCHECK(error_handler); |
| 32 } | 34 } |
| 33 | 35 |
| 34 PreferenceChangeProcessor::~PreferenceChangeProcessor() { | 36 PreferenceChangeProcessor::~PreferenceChangeProcessor() { |
| 35 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 37 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 36 } | 38 } |
| 37 | 39 |
| 38 void PreferenceChangeProcessor::Observe(NotificationType type, | 40 void PreferenceChangeProcessor::Observe(NotificationType type, |
| 39 const NotificationSource& source, | 41 const NotificationSource& source, |
| 40 const NotificationDetails& details) { | 42 const NotificationDetails& details) { |
| 41 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 43 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 42 DCHECK(running()); | 44 DCHECK(running()); |
| 43 DCHECK(NotificationType::PREF_CHANGED == type); | 45 DCHECK(NotificationType::PREF_CHANGED == type); |
| 44 DCHECK_EQ(pref_service_, Source<PrefService>(source).ptr()); | 46 DCHECK_EQ(pref_service_, Source<PrefService>(source).ptr()); |
| 45 | 47 |
| 48 // Avoid recursion. |
| 49 if (processing_pref_change_) |
| 50 return; |
| 51 |
| 52 AutoReset<bool> guard(&processing_pref_change_, true); |
| 46 std::string* name = Details<std::string>(details).ptr(); | 53 std::string* name = Details<std::string>(details).ptr(); |
| 47 const PrefService::Preference* preference = | 54 const PrefService::Preference* preference = |
| 48 pref_service_->FindPreference((*name).c_str()); | 55 pref_service_->FindPreference((*name).c_str()); |
| 49 DCHECK(preference); | 56 DCHECK(preference); |
| 50 | 57 int64 sync_id = model_associator_->GetSyncIdFromChromeId(*name); |
| 51 // TODO(mnissler): Detect preference->IsUserControlled() state changes here | 58 bool user_modifiable = preference->IsUserModifiable(); |
| 52 // and call into PreferenceModelAssociator to associate/disassociate sync | 59 if (!user_modifiable) { |
| 53 // nodes when the state changes. | 60 // We do not track preferences the user cannot change. |
| 54 | 61 model_associator_->Disassociate(sync_id); |
| 55 // Do not pollute sync data with values coming from policy, extensions or the | |
| 56 // commandline. | |
| 57 if (!preference->IsUserModifiable()) | |
| 58 return; | 62 return; |
| 63 } |
| 59 | 64 |
| 60 sync_api::WriteTransaction trans(share_handle()); | 65 sync_api::WriteTransaction trans(share_handle()); |
| 61 sync_api::WriteNode node(&trans); | 66 sync_api::WriteNode node(&trans); |
| 62 | 67 |
| 63 // Since we don't create sync nodes for preferences that still have | 68 // Since we don't create sync nodes for preferences that are not under control |
| 64 // their default values, this changed preference may not have a sync | 69 // of the user or still have their default value, this changed preference may |
| 65 // node yet. If not, create it. | 70 // not have a sync node yet. If so, we create a node. Similarly, a preference |
| 66 int64 sync_id = model_associator_->GetSyncIdFromChromeId(*name); | 71 // may become user-modifiable (e.g. due to laxer policy configuration), in |
| 72 // which case we also need to create a sync node and associate it. |
| 67 if (sync_api::kInvalidId == sync_id) { | 73 if (sync_api::kInvalidId == sync_id) { |
| 68 sync_api::ReadNode root(&trans); | 74 sync_api::ReadNode root(&trans); |
| 69 if (!root.InitByTagLookup(browser_sync::kPreferencesTag)) { | 75 if (!root.InitByTagLookup(browser_sync::kPreferencesTag)) { |
| 70 error_handler()->OnUnrecoverableError(FROM_HERE, "Can't find root."); | 76 error_handler()->OnUnrecoverableError(FROM_HERE, "Can't find root."); |
| 71 return; | 77 return; |
| 72 } | 78 } |
| 73 | 79 |
| 74 if (!node.InitUniqueByCreation(syncable::PREFERENCES, root, *name)) { | 80 // InitPrefNodeAndAssociate takes care of writing the value to the sync |
| 75 error_handler()->OnUnrecoverableError( | 81 // node if appropriate. |
| 76 FROM_HERE, | 82 if (!model_associator_->InitPrefNodeAndAssociate(&trans, |
| 77 "Failed to create preference sync node."); | 83 root, |
| 78 return; | 84 preference)) { |
| 85 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 86 "Can't create sync node."); |
| 79 } | 87 } |
| 88 return; |
| 89 } |
| 80 | 90 |
| 81 model_associator_->Associate(preference, node.GetId()); | 91 if (!node.InitByIdLookup(sync_id)) { |
| 82 } else { | 92 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 83 if (!node.InitByIdLookup(sync_id)) { | 93 "Preference node lookup failed."); |
| 84 error_handler()->OnUnrecoverableError(FROM_HERE, | 94 return; |
| 85 "Preference node lookup failed."); | |
| 86 return; | |
| 87 } | |
| 88 } | 95 } |
| 89 | 96 |
| 90 if (!PreferenceModelAssociator::WritePreferenceToNode( | 97 if (!PreferenceModelAssociator::WritePreferenceToNode( |
| 91 preference->name(), | 98 preference->name(), |
| 92 *preference->GetValue(), | 99 *preference->GetValue(), |
| 93 &node)) { | 100 &node)) { |
| 94 error_handler()->OnUnrecoverableError(FROM_HERE, | 101 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 95 "Failed to update preference node."); | 102 "Failed to update preference node."); |
| 96 return; | 103 return; |
| 97 } | 104 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 void PreferenceChangeProcessor::StopObserving() { | 217 void PreferenceChangeProcessor::StopObserving() { |
| 211 DCHECK(pref_service_); | 218 DCHECK(pref_service_); |
| 212 for (std::set<std::string>::const_iterator it = | 219 for (std::set<std::string>::const_iterator it = |
| 213 model_associator_->synced_preferences().begin(); | 220 model_associator_->synced_preferences().begin(); |
| 214 it != model_associator_->synced_preferences().end(); ++it) { | 221 it != model_associator_->synced_preferences().end(); ++it) { |
| 215 pref_service_->RemovePrefObserver((*it).c_str(), this); | 222 pref_service_->RemovePrefObserver((*it).c_str(), this); |
| 216 } | 223 } |
| 217 } | 224 } |
| 218 | 225 |
| 219 } // namespace browser_sync | 226 } // namespace browser_sync |
| OLD | NEW |