| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/prefs/pref_service_syncable.h" |
| |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/prefs/default_pref_store.h" |
| #include "base/prefs/overlay_user_pref_store.h" |
| #include "base/prefs/pref_notifier_impl.h" |
| #include "base/prefs/pref_registry.h" |
| #include "base/prefs/pref_value_store.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/value_conversions.h" |
| #include "chrome/browser/prefs/pref_model_associator.h" |
| #include "chrome/browser/prefs/pref_service_syncable_observer.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/prefs/prefs_tab_helper.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| |
| // static |
| PrefServiceSyncable* PrefServiceSyncable::FromProfile(Profile* profile) { |
| return static_cast<PrefServiceSyncable*>(profile->GetPrefs()); |
| } |
| |
| // static |
| PrefServiceSyncable* PrefServiceSyncable::IncognitoFromProfile( |
| Profile* profile) { |
| return static_cast<PrefServiceSyncable*>(profile->GetOffTheRecordPrefs()); |
| } |
| |
| PrefServiceSyncable::PrefServiceSyncable( |
| PrefNotifierImpl* pref_notifier, |
| PrefValueStore* pref_value_store, |
| PersistentPrefStore* user_prefs, |
| user_prefs::PrefRegistrySyncable* pref_registry, |
| base::Callback<void(PersistentPrefStore::PrefReadError)> |
| read_error_callback, |
| bool async) |
| : PrefService(pref_notifier, |
| pref_value_store, |
| user_prefs, |
| pref_registry, |
| read_error_callback, |
| async), |
| pref_sync_associator_(syncer::PREFERENCES), |
| priority_pref_sync_associator_(syncer::PRIORITY_PREFERENCES) { |
| pref_sync_associator_.SetPrefService(this); |
| priority_pref_sync_associator_.SetPrefService(this); |
| |
| // Let PrefModelAssociators know about changes to preference values. |
| pref_value_store->set_callback( |
| base::Bind(&PrefServiceSyncable::ProcessPrefChange, |
| base::Unretained(this))); |
| |
| // Add already-registered syncable preferences to PrefModelAssociator. |
| const user_prefs::PrefRegistrySyncable::PrefToStatus& syncable_preferences = |
| pref_registry->syncable_preferences(); |
| for (user_prefs::PrefRegistrySyncable::PrefToStatus::const_iterator it = |
| syncable_preferences.begin(); |
| it != syncable_preferences.end(); |
| ++it) { |
| AddRegisteredSyncablePreference(it->first.c_str(), it->second); |
| } |
| |
| // Watch for syncable preferences registered after this point. |
| pref_registry->SetSyncableRegistrationCallback( |
| base::Bind(&PrefServiceSyncable::AddRegisteredSyncablePreference, |
| base::Unretained(this))); |
| } |
| |
| PrefServiceSyncable::~PrefServiceSyncable() { |
| // Remove our callback from the registry, since it may outlive us. |
| user_prefs::PrefRegistrySyncable* registry = |
| static_cast<user_prefs::PrefRegistrySyncable*>(pref_registry_.get()); |
| registry->SetSyncableRegistrationCallback( |
| user_prefs::PrefRegistrySyncable::SyncableRegistrationCallback()); |
| } |
| |
| PrefServiceSyncable* PrefServiceSyncable::CreateIncognitoPrefService( |
| PrefStore* incognito_extension_prefs) { |
| pref_service_forked_ = true; |
| PrefNotifierImpl* pref_notifier = new PrefNotifierImpl(); |
| OverlayUserPrefStore* incognito_pref_store = |
| new OverlayUserPrefStore(user_pref_store_.get()); |
| PrefsTabHelper::InitIncognitoUserPrefStore(incognito_pref_store); |
| |
| scoped_refptr<user_prefs::PrefRegistrySyncable> forked_registry = |
| static_cast<user_prefs::PrefRegistrySyncable*>( |
| pref_registry_.get())->ForkForIncognito(); |
| PrefServiceSyncable* incognito_service = new PrefServiceSyncable( |
| pref_notifier, |
| pref_value_store_->CloneAndSpecialize(NULL, // managed |
| NULL, // supervised_user |
| incognito_extension_prefs, |
| NULL, // command_line_prefs |
| incognito_pref_store, |
| NULL, // recommended |
| forked_registry->defaults().get(), |
| pref_notifier), |
| incognito_pref_store, |
| forked_registry.get(), |
| read_error_callback_, |
| false); |
| return incognito_service; |
| } |
| |
| bool PrefServiceSyncable::IsSyncing() { |
| return pref_sync_associator_.models_associated(); |
| } |
| |
| bool PrefServiceSyncable::IsPrioritySyncing() { |
| return priority_pref_sync_associator_.models_associated(); |
| } |
| |
| bool PrefServiceSyncable::IsPrefSynced(const std::string& name) const { |
| return pref_sync_associator_.IsPrefSynced(name) || |
| priority_pref_sync_associator_.IsPrefSynced(name); |
| } |
| |
| void PrefServiceSyncable::AddObserver(PrefServiceSyncableObserver* observer) { |
| observer_list_.AddObserver(observer); |
| } |
| |
| void PrefServiceSyncable::RemoveObserver( |
| PrefServiceSyncableObserver* observer) { |
| observer_list_.RemoveObserver(observer); |
| } |
| |
| syncer::SyncableService* PrefServiceSyncable::GetSyncableService( |
| const syncer::ModelType& type) { |
| if (type == syncer::PREFERENCES) { |
| return &pref_sync_associator_; |
| } else if (type == syncer::PRIORITY_PREFERENCES) { |
| return &priority_pref_sync_associator_; |
| } else { |
| NOTREACHED() << "invalid model type: " << type; |
| return NULL; |
| } |
| } |
| |
| void PrefServiceSyncable::UpdateCommandLinePrefStore( |
| PrefStore* cmd_line_store) { |
| // If |pref_service_forked_| is true, then this PrefService and the forked |
| // copies will be out of sync. |
| DCHECK(!pref_service_forked_); |
| PrefService::UpdateCommandLinePrefStore(cmd_line_store); |
| } |
| |
| void PrefServiceSyncable::AddSyncedPrefObserver( |
| const std::string& name, |
| SyncedPrefObserver* observer) { |
| pref_sync_associator_.AddSyncedPrefObserver(name, observer); |
| priority_pref_sync_associator_.AddSyncedPrefObserver(name, observer); |
| } |
| |
| void PrefServiceSyncable::RemoveSyncedPrefObserver( |
| const std::string& name, |
| SyncedPrefObserver* observer) { |
| pref_sync_associator_.RemoveSyncedPrefObserver(name, observer); |
| priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer); |
| } |
| |
| void PrefServiceSyncable::AddRegisteredSyncablePreference( |
| const char* path, |
| const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status) { |
| DCHECK(FindPreference(path)); |
| if (sync_status == user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) { |
| pref_sync_associator_.RegisterPref(path); |
| } else if (sync_status == |
| user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { |
| priority_pref_sync_associator_.RegisterPref(path); |
| } else { |
| NOTREACHED() << "invalid sync_status: " << sync_status; |
| } |
| } |
| |
| void PrefServiceSyncable::OnIsSyncingChanged() { |
| FOR_EACH_OBSERVER(PrefServiceSyncableObserver, observer_list_, |
| OnIsSyncingChanged()); |
| } |
| |
| void PrefServiceSyncable::ProcessPrefChange(const std::string& name) { |
| pref_sync_associator_.ProcessPrefChange(name); |
| priority_pref_sync_associator_.ProcessPrefChange(name); |
| } |