blob: 0a8613c84e2954faffe09f2d30ba404dcd2a8836 [file] [log] [blame]
// 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);
}