Home | History | Annotate | Download | only in prefs
      1 // Copyright (c) 2011 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 "chrome/browser/prefs/pref_notifier_impl.h"
      6 
      7 #include "base/stl_util-inl.h"
      8 #include "chrome/browser/prefs/pref_service.h"
      9 #include "content/common/notification_observer.h"
     10 #include "content/common/notification_service.h"
     11 
     12 PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
     13     : pref_service_(service) {
     14 }
     15 
     16 PrefNotifierImpl::~PrefNotifierImpl() {
     17   DCHECK(CalledOnValidThread());
     18 
     19   // Verify that there are no pref observers when we shut down.
     20   for (PrefObserverMap::iterator it = pref_observers_.begin();
     21        it != pref_observers_.end(); ++it) {
     22     NotificationObserverList::Iterator obs_iterator(*(it->second));
     23     if (obs_iterator.GetNext()) {
     24       LOG(WARNING) << "pref observer found at shutdown " << it->first;
     25     }
     26   }
     27 
     28   STLDeleteContainerPairSecondPointers(pref_observers_.begin(),
     29                                        pref_observers_.end());
     30   pref_observers_.clear();
     31 }
     32 
     33 void PrefNotifierImpl::AddPrefObserver(const char* path,
     34                                        NotificationObserver* obs) {
     35   // Get the pref observer list associated with the path.
     36   NotificationObserverList* observer_list = NULL;
     37   const PrefObserverMap::iterator observer_iterator =
     38       pref_observers_.find(path);
     39   if (observer_iterator == pref_observers_.end()) {
     40     observer_list = new NotificationObserverList;
     41     pref_observers_[path] = observer_list;
     42   } else {
     43     observer_list = observer_iterator->second;
     44   }
     45 
     46   // Verify that this observer doesn't already exist.
     47   NotificationObserverList::Iterator it(*observer_list);
     48   NotificationObserver* existing_obs;
     49   while ((existing_obs = it.GetNext()) != NULL) {
     50     DCHECK(existing_obs != obs) << path << " observer already registered";
     51     if (existing_obs == obs)
     52       return;
     53   }
     54 
     55   // Ok, safe to add the pref observer.
     56   observer_list->AddObserver(obs);
     57 }
     58 
     59 void PrefNotifierImpl::RemovePrefObserver(const char* path,
     60                                           NotificationObserver* obs) {
     61   DCHECK(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   NotificationObserverList* observer_list = observer_iterator->second;
     70   observer_list->RemoveObserver(obs);
     71 }
     72 
     73 void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
     74   FireObservers(path);
     75 }
     76 
     77 void PrefNotifierImpl::OnInitializationCompleted() {
     78   DCHECK(CalledOnValidThread());
     79 
     80   NotificationService::current()->Notify(
     81       NotificationType::PREF_INITIALIZATION_COMPLETED,
     82       Source<PrefService>(pref_service_),
     83       NotificationService::NoDetails());
     84 }
     85 
     86 void PrefNotifierImpl::FireObservers(const std::string& path) {
     87   DCHECK(CalledOnValidThread());
     88 
     89   // Only send notifications for registered preferences.
     90   if (!pref_service_->FindPreference(path.c_str()))
     91     return;
     92 
     93   const PrefObserverMap::iterator observer_iterator =
     94       pref_observers_.find(path);
     95   if (observer_iterator == pref_observers_.end())
     96     return;
     97 
     98   NotificationObserverList::Iterator it(*(observer_iterator->second));
     99   NotificationObserver* observer;
    100   while ((observer = it.GetNext()) != NULL) {
    101     observer->Observe(NotificationType::PREF_CHANGED,
    102                       Source<PrefService>(pref_service_),
    103                       Details<const std::string>(&path));
    104   }
    105 }
    106