Home | History | Annotate | Download | only in prefs
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/prefs/pref_notifier_impl.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/stl_util.h"
     10 
     11 PrefNotifierImpl::PrefNotifierImpl()
     12     : pref_service_(NULL) {
     13 }
     14 
     15 PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
     16     : pref_service_(service) {
     17 }
     18 
     19 PrefNotifierImpl::~PrefNotifierImpl() {
     20   DCHECK(thread_checker_.CalledOnValidThread());
     21 
     22   // Verify that there are no pref observers when we shut down.
     23   for (PrefObserverMap::iterator it = pref_observers_.begin();
     24        it != pref_observers_.end(); ++it) {
     25     PrefObserverList::Iterator obs_iterator(*(it->second));
     26     if (obs_iterator.GetNext()) {
     27       LOG(WARNING) << "pref observer found at shutdown " << it->first;
     28     }
     29   }
     30 
     31   // Same for initialization observers.
     32   if (!init_observers_.empty())
     33     LOG(WARNING) << "Init observer found at shutdown.";
     34 
     35   STLDeleteContainerPairSecondPointers(pref_observers_.begin(),
     36                                        pref_observers_.end());
     37   pref_observers_.clear();
     38   init_observers_.clear();
     39 }
     40 
     41 void PrefNotifierImpl::AddPrefObserver(const char* path,
     42                                        PrefObserver* obs) {
     43   // Get the pref observer list associated with the path.
     44   PrefObserverList* observer_list = NULL;
     45   const PrefObserverMap::iterator observer_iterator =
     46       pref_observers_.find(path);
     47   if (observer_iterator == pref_observers_.end()) {
     48     observer_list = new PrefObserverList;
     49     pref_observers_[path] = observer_list;
     50   } else {
     51     observer_list = observer_iterator->second;
     52   }
     53 
     54   // Add the pref observer. ObserverList will DCHECK if it already is
     55   // in the list.
     56   observer_list->AddObserver(obs);
     57 }
     58 
     59 void PrefNotifierImpl::RemovePrefObserver(const char* path,
     60                                           PrefObserver* obs) {
     61   DCHECK(thread_checker_.CalledOnValidThread());
     62 
     63   const PrefObserverMap::iterator observer_iterator =
     64       pref_observers_.find(path);
     65   if (observer_iterator == pref_observers_.end()) {
     66     return;
     67   }
     68 
     69   PrefObserverList* observer_list = observer_iterator->second;
     70   observer_list->RemoveObserver(obs);
     71 }
     72 
     73 void PrefNotifierImpl::AddInitObserver(base::Callback<void(bool)> obs) {
     74   init_observers_.push_back(obs);
     75 }
     76 
     77 void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
     78   FireObservers(path);
     79 }
     80 
     81 void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
     82   DCHECK(thread_checker_.CalledOnValidThread());
     83 
     84   // We must make a copy of init_observers_ and clear it before we run
     85   // observers, or we can end up in this method re-entrantly before
     86   // clearing the observers list.
     87   PrefInitObserverList observers(init_observers_);
     88   init_observers_.clear();
     89 
     90   for (PrefInitObserverList::iterator it = observers.begin();
     91        it != observers.end();
     92        ++it) {
     93     it->Run(succeeded);
     94   }
     95 }
     96 
     97 void PrefNotifierImpl::FireObservers(const std::string& path) {
     98   DCHECK(thread_checker_.CalledOnValidThread());
     99 
    100   // Only send notifications for registered preferences.
    101   if (!pref_service_->FindPreference(path.c_str()))
    102     return;
    103 
    104   const PrefObserverMap::iterator observer_iterator =
    105       pref_observers_.find(path);
    106   if (observer_iterator == pref_observers_.end())
    107     return;
    108 
    109   FOR_EACH_OBSERVER(PrefObserver,
    110                     *(observer_iterator->second),
    111                     OnPreferenceChanged(pref_service_, path));
    112 }
    113 
    114 void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
    115   DCHECK(pref_service_ == NULL);
    116   pref_service_ = pref_service;
    117 }
    118