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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/prefs/pref_service_syncable.h" 6 7 #include "base/bind.h" 8 #include "base/files/file_path.h" 9 #include "base/prefs/default_pref_store.h" 10 #include "base/prefs/overlay_user_pref_store.h" 11 #include "base/prefs/pref_notifier_impl.h" 12 #include "base/prefs/pref_registry.h" 13 #include "base/prefs/pref_value_store.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/value_conversions.h" 16 #include "chrome/browser/prefs/pref_model_associator.h" 17 #include "chrome/browser/prefs/pref_service_syncable_observer.h" 18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/ui/prefs/prefs_tab_helper.h" 20 #include "components/pref_registry/pref_registry_syncable.h" 21 22 // static 23 PrefServiceSyncable* PrefServiceSyncable::FromProfile(Profile* profile) { 24 return static_cast<PrefServiceSyncable*>(profile->GetPrefs()); 25 } 26 27 // static 28 PrefServiceSyncable* PrefServiceSyncable::IncognitoFromProfile( 29 Profile* profile) { 30 return static_cast<PrefServiceSyncable*>(profile->GetOffTheRecordPrefs()); 31 } 32 33 PrefServiceSyncable::PrefServiceSyncable( 34 PrefNotifierImpl* pref_notifier, 35 PrefValueStore* pref_value_store, 36 PersistentPrefStore* user_prefs, 37 user_prefs::PrefRegistrySyncable* pref_registry, 38 base::Callback<void(PersistentPrefStore::PrefReadError)> 39 read_error_callback, 40 bool async) 41 : PrefService(pref_notifier, 42 pref_value_store, 43 user_prefs, 44 pref_registry, 45 read_error_callback, 46 async), 47 pref_sync_associator_(syncer::PREFERENCES), 48 priority_pref_sync_associator_(syncer::PRIORITY_PREFERENCES) { 49 pref_sync_associator_.SetPrefService(this); 50 priority_pref_sync_associator_.SetPrefService(this); 51 52 // Let PrefModelAssociators know about changes to preference values. 53 pref_value_store->set_callback( 54 base::Bind(&PrefServiceSyncable::ProcessPrefChange, 55 base::Unretained(this))); 56 57 // Add already-registered syncable preferences to PrefModelAssociator. 58 const user_prefs::PrefRegistrySyncable::PrefToStatus& syncable_preferences = 59 pref_registry->syncable_preferences(); 60 for (user_prefs::PrefRegistrySyncable::PrefToStatus::const_iterator it = 61 syncable_preferences.begin(); 62 it != syncable_preferences.end(); 63 ++it) { 64 AddRegisteredSyncablePreference(it->first.c_str(), it->second); 65 } 66 67 // Watch for syncable preferences registered after this point. 68 pref_registry->SetSyncableRegistrationCallback( 69 base::Bind(&PrefServiceSyncable::AddRegisteredSyncablePreference, 70 base::Unretained(this))); 71 } 72 73 PrefServiceSyncable::~PrefServiceSyncable() { 74 // Remove our callback from the registry, since it may outlive us. 75 user_prefs::PrefRegistrySyncable* registry = 76 static_cast<user_prefs::PrefRegistrySyncable*>(pref_registry_.get()); 77 registry->SetSyncableRegistrationCallback( 78 user_prefs::PrefRegistrySyncable::SyncableRegistrationCallback()); 79 } 80 81 PrefServiceSyncable* PrefServiceSyncable::CreateIncognitoPrefService( 82 PrefStore* incognito_extension_prefs) { 83 pref_service_forked_ = true; 84 PrefNotifierImpl* pref_notifier = new PrefNotifierImpl(); 85 OverlayUserPrefStore* incognito_pref_store = 86 new OverlayUserPrefStore(user_pref_store_.get()); 87 PrefsTabHelper::InitIncognitoUserPrefStore(incognito_pref_store); 88 89 scoped_refptr<user_prefs::PrefRegistrySyncable> forked_registry = 90 static_cast<user_prefs::PrefRegistrySyncable*>( 91 pref_registry_.get())->ForkForIncognito(); 92 PrefServiceSyncable* incognito_service = new PrefServiceSyncable( 93 pref_notifier, 94 pref_value_store_->CloneAndSpecialize(NULL, // managed 95 NULL, // supervised_user 96 incognito_extension_prefs, 97 NULL, // command_line_prefs 98 incognito_pref_store, 99 NULL, // recommended 100 forked_registry->defaults().get(), 101 pref_notifier), 102 incognito_pref_store, 103 forked_registry.get(), 104 read_error_callback_, 105 false); 106 return incognito_service; 107 } 108 109 bool PrefServiceSyncable::IsSyncing() { 110 return pref_sync_associator_.models_associated(); 111 } 112 113 bool PrefServiceSyncable::IsPrioritySyncing() { 114 return priority_pref_sync_associator_.models_associated(); 115 } 116 117 bool PrefServiceSyncable::IsPrefSynced(const std::string& name) const { 118 return pref_sync_associator_.IsPrefSynced(name) || 119 priority_pref_sync_associator_.IsPrefSynced(name); 120 } 121 122 void PrefServiceSyncable::AddObserver(PrefServiceSyncableObserver* observer) { 123 observer_list_.AddObserver(observer); 124 } 125 126 void PrefServiceSyncable::RemoveObserver( 127 PrefServiceSyncableObserver* observer) { 128 observer_list_.RemoveObserver(observer); 129 } 130 131 syncer::SyncableService* PrefServiceSyncable::GetSyncableService( 132 const syncer::ModelType& type) { 133 if (type == syncer::PREFERENCES) { 134 return &pref_sync_associator_; 135 } else if (type == syncer::PRIORITY_PREFERENCES) { 136 return &priority_pref_sync_associator_; 137 } else { 138 NOTREACHED() << "invalid model type: " << type; 139 return NULL; 140 } 141 } 142 143 void PrefServiceSyncable::UpdateCommandLinePrefStore( 144 PrefStore* cmd_line_store) { 145 // If |pref_service_forked_| is true, then this PrefService and the forked 146 // copies will be out of sync. 147 DCHECK(!pref_service_forked_); 148 PrefService::UpdateCommandLinePrefStore(cmd_line_store); 149 } 150 151 void PrefServiceSyncable::AddSyncedPrefObserver( 152 const std::string& name, 153 SyncedPrefObserver* observer) { 154 pref_sync_associator_.AddSyncedPrefObserver(name, observer); 155 priority_pref_sync_associator_.AddSyncedPrefObserver(name, observer); 156 } 157 158 void PrefServiceSyncable::RemoveSyncedPrefObserver( 159 const std::string& name, 160 SyncedPrefObserver* observer) { 161 pref_sync_associator_.RemoveSyncedPrefObserver(name, observer); 162 priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer); 163 } 164 165 void PrefServiceSyncable::AddRegisteredSyncablePreference( 166 const char* path, 167 const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status) { 168 DCHECK(FindPreference(path)); 169 if (sync_status == user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) { 170 pref_sync_associator_.RegisterPref(path); 171 } else if (sync_status == 172 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { 173 priority_pref_sync_associator_.RegisterPref(path); 174 } else { 175 NOTREACHED() << "invalid sync_status: " << sync_status; 176 } 177 } 178 179 void PrefServiceSyncable::OnIsSyncingChanged() { 180 FOR_EACH_OBSERVER(PrefServiceSyncableObserver, observer_list_, 181 OnIsSyncingChanged()); 182 } 183 184 void PrefServiceSyncable::ProcessPrefChange(const std::string& name) { 185 pref_sync_associator_.ProcessPrefChange(name); 186 priority_pref_sync_associator_.ProcessPrefChange(name); 187 } 188