pref_notifier_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_notifier_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrefNotifierImpl::PrefNotifierImpl()
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pref_service_(NULL) {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pref_service_(service) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrefNotifierImpl::~PrefNotifierImpl() {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that there are no pref observers when we shut down.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PrefObserverMap::iterator it = pref_observers_.begin();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pref_observers_.end(); ++it) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrefObserverList::Iterator obs_iterator(*(it->second));
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (obs_iterator.GetNext()) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "pref observer found at shutdown " << it->first;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same for initialization observers.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!init_observers_.empty())
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Init observer found at shutdown.";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(pref_observers_.begin(),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       pref_observers_.end());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_observers_.clear();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_observers_.clear();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::AddPrefObserver(const char* path,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PrefObserver* obs) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the pref observer list associated with the path.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefObserverList* observer_list = NULL;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PrefObserverMap::iterator observer_iterator =
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pref_observers_.find(path);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_iterator == pref_observers_.end()) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_list = new PrefObserverList;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_observers_[path] = observer_list;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_list = observer_iterator->second;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the pref observer. ObserverList will DCHECK if it already is
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the list.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_list->AddObserver(obs);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::RemovePrefObserver(const char* path,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          PrefObserver* obs) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PrefObserverMap::iterator observer_iterator =
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pref_observers_.find(path);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_iterator == pref_observers_.end()) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefObserverList* observer_list = observer_iterator->second;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_list->RemoveObserver(obs);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::AddInitObserver(base::Callback<void(bool)> obs) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_observers_.push_back(obs);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FireObservers(path);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We must make a copy of init_observers_ and clear it before we run
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // observers, or we can end up in this method re-entrantly before
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clearing the observers list.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefInitObserverList observers(init_observers_);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_observers_.clear();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PrefInitObserverList::iterator it = observers.begin();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != observers.end();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->Run(succeeded);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::FireObservers(const std::string& path) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only send notifications for registered preferences.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pref_service_->FindPreference(path.c_str()))
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PrefObserverMap::iterator observer_iterator =
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pref_observers_.find(path);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_iterator == pref_observers_.end())
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PrefObserver,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    *(observer_iterator->second),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnPreferenceChanged(pref_service_, path));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pref_service_ == NULL);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_service_ = pref_service;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
118