// 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 "base/prefs/pref_notifier_impl.h" #include "base/logging.h" #include "base/prefs/pref_service.h" #include "base/stl_util.h" PrefNotifierImpl::PrefNotifierImpl() : pref_service_(NULL) { } PrefNotifierImpl::PrefNotifierImpl(PrefService* service) : pref_service_(service) { } PrefNotifierImpl::~PrefNotifierImpl() { DCHECK(thread_checker_.CalledOnValidThread()); // Verify that there are no pref observers when we shut down. for (PrefObserverMap::iterator it = pref_observers_.begin(); it != pref_observers_.end(); ++it) { PrefObserverList::Iterator obs_iterator(*(it->second)); if (obs_iterator.GetNext()) { LOG(WARNING) << "pref observer found at shutdown " << it->first; } } // Same for initialization observers. if (!init_observers_.empty()) LOG(WARNING) << "Init observer found at shutdown."; STLDeleteContainerPairSecondPointers(pref_observers_.begin(), pref_observers_.end()); pref_observers_.clear(); init_observers_.clear(); } void PrefNotifierImpl::AddPrefObserver(const char* path, PrefObserver* obs) { // Get the pref observer list associated with the path. PrefObserverList* observer_list = NULL; const PrefObserverMap::iterator observer_iterator = pref_observers_.find(path); if (observer_iterator == pref_observers_.end()) { observer_list = new PrefObserverList; pref_observers_[path] = observer_list; } else { observer_list = observer_iterator->second; } // Add the pref observer. ObserverList will DCHECK if it already is // in the list. observer_list->AddObserver(obs); } void PrefNotifierImpl::RemovePrefObserver(const char* path, PrefObserver* obs) { DCHECK(thread_checker_.CalledOnValidThread()); const PrefObserverMap::iterator observer_iterator = pref_observers_.find(path); if (observer_iterator == pref_observers_.end()) { return; } PrefObserverList* observer_list = observer_iterator->second; observer_list->RemoveObserver(obs); } void PrefNotifierImpl::AddInitObserver(base::Callback<void(bool)> obs) { init_observers_.push_back(obs); } void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) { FireObservers(path); } void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) { DCHECK(thread_checker_.CalledOnValidThread()); // We must make a copy of init_observers_ and clear it before we run // observers, or we can end up in this method re-entrantly before // clearing the observers list. PrefInitObserverList observers(init_observers_); init_observers_.clear(); for (PrefInitObserverList::iterator it = observers.begin(); it != observers.end(); ++it) { it->Run(succeeded); } } void PrefNotifierImpl::FireObservers(const std::string& path) { DCHECK(thread_checker_.CalledOnValidThread()); // Only send notifications for registered preferences. if (!pref_service_->FindPreference(path.c_str())) return; const PrefObserverMap::iterator observer_iterator = pref_observers_.find(path); if (observer_iterator == pref_observers_.end()) return; FOR_EACH_OBSERVER(PrefObserver, *(observer_iterator->second), OnPreferenceChanged(pref_service_, path)); } void PrefNotifierImpl::SetPrefService(PrefService* pref_service) { DCHECK(pref_service_ == NULL); pref_service_ = pref_service; }