| // 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 "components/sync_preferences/pref_service_syncable.h" |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/files/file_path.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/value_conversions.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| #include "components/prefs/default_pref_store.h" |
| #include "components/prefs/overlay_user_pref_store.h" |
| #include "components/prefs/pref_notifier_impl.h" |
| #include "components/prefs/pref_registry.h" |
| #include "components/prefs/pref_value_store.h" |
| #include "components/sync_preferences/pref_model_associator.h" |
| #include "components/sync_preferences/pref_service_syncable_observer.h" |
| |
| namespace sync_preferences { |
| |
| PrefServiceSyncable::PrefServiceSyncable( |
| PrefNotifierImpl* pref_notifier, |
| PrefValueStore* pref_value_store, |
| PersistentPrefStore* user_prefs, |
| user_prefs::PrefRegistrySyncable* pref_registry, |
| const PrefModelAssociatorClient* pref_model_associator_client, |
| 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_service_forked_(false), |
| pref_sync_associator_(pref_model_associator_client, syncer::PREFERENCES), |
| priority_pref_sync_associator_(pref_model_associator_client, |
| 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. |
| for (PrefRegistry::const_iterator it = pref_registry->begin(); |
| it != pref_registry->end(); ++it) { |
| const std::string& path = it->first; |
| AddRegisteredSyncablePreference(path, |
| pref_registry_->GetRegistrationFlags(path)); |
| } |
| |
| // 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_pref_store, |
| const std::vector<const char*>& overlay_pref_names) { |
| pref_service_forked_ = true; |
| PrefNotifierImpl* pref_notifier = new PrefNotifierImpl(); |
| OverlayUserPrefStore* incognito_pref_store = |
| new OverlayUserPrefStore(user_pref_store_.get()); |
| for (const char* overlay_pref_name : overlay_pref_names) |
| incognito_pref_store->RegisterOverlayPref(overlay_pref_name); |
| |
| 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_pref_store, |
| NULL, // command_line_prefs |
| incognito_pref_store, |
| NULL, // recommended |
| forked_registry->defaults().get(), |
| pref_notifier), |
| incognito_pref_store, forked_registry.get(), |
| pref_sync_associator_.client(), 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::RegisterMergeDataFinishedCallback( |
| const base::Closure& callback) { |
| pref_sync_associator_.RegisterMergeDataFinishedCallback(callback); |
| } |
| |
| // Set the PrefModelAssociatorClient to use for that object during tests. |
| void PrefServiceSyncable::SetPrefModelAssociatorClientForTesting( |
| const PrefModelAssociatorClient* pref_model_associator_client) { |
| pref_sync_associator_.SetPrefModelAssociatorClientForTesting( |
| pref_model_associator_client); |
| priority_pref_sync_associator_.SetPrefModelAssociatorClientForTesting( |
| pref_model_associator_client); |
| } |
| |
| void PrefServiceSyncable::AddRegisteredSyncablePreference( |
| const std::string& path, |
| uint32_t flags) { |
| DCHECK(FindPreference(path)); |
| if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) { |
| pref_sync_associator_.RegisterPref(path.c_str()); |
| } else if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { |
| priority_pref_sync_associator_.RegisterPref(path.c_str()); |
| } |
| } |
| |
| void PrefServiceSyncable::OnIsSyncingChanged() { |
| for (auto& observer : observer_list_) |
| observer.OnIsSyncingChanged(); |
| } |
| |
| void PrefServiceSyncable::ProcessPrefChange(const std::string& name) { |
| pref_sync_associator_.ProcessPrefChange(name); |
| priority_pref_sync_associator_.ProcessPrefChange(name); |
| } |
| |
| } // namespace sync_preferences |