diff options
Diffstat (limited to 'components/syncable_prefs/pref_service_syncable.cc')
-rw-r--r-- | components/syncable_prefs/pref_service_syncable.cc | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/components/syncable_prefs/pref_service_syncable.cc b/components/syncable_prefs/pref_service_syncable.cc new file mode 100644 index 0000000..46f7ec7 --- /dev/null +++ b/components/syncable_prefs/pref_service_syncable.cc @@ -0,0 +1,182 @@ +// 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/syncable_prefs/pref_service_syncable.h" + +#include "base/bind.h" +#include "base/callback.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 "components/pref_registry/pref_registry_syncable.h" +#include "components/syncable_prefs/pref_model_associator.h" +#include "components/syncable_prefs/pref_service_syncable_observer.h" + +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_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); +} + +// 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 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_EACH_OBSERVER(PrefServiceSyncableObserver, observer_list_, + OnIsSyncingChanged()); +} + +void PrefServiceSyncable::ProcessPrefChange(const std::string& name) { + pref_sync_associator_.ProcessPrefChange(name); + priority_pref_sync_associator_.ProcessPrefChange(name); +} |