Remove content::NotificationObserver dependency from most Prefs code.
Instead of using content::NotificationObserver, introduce specific
type-safe observer classes and update users to use them. In a very
large number of cases this was the users' only reason for being a
content::NotificationObserver and they would have a lot of
boiler-plate code such as a DCHECK on the notification type and
unpacking of the generic NotificationDetails types, so this change
removes a bunch of boilerplate and introduces more type safety.
This is part of enabling more of the Prefs code to live in
base/prefs/.
[email protected],[email protected]
BUG=155525
Review URL: https://chromiumcodereview.appspot.com/11345008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165414 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/prefs/pref_notifier_impl.cc b/chrome/browser/prefs/pref_notifier_impl.cc
index a226685c..9bdf322 100644
--- a/chrome/browser/prefs/pref_notifier_impl.cc
+++ b/chrome/browser/prefs/pref_notifier_impl.cc
@@ -7,9 +7,6 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_service.h"
PrefNotifierImpl::PrefNotifierImpl()
: pref_service_(NULL) {
@@ -25,45 +22,42 @@
// Verify that there are no pref observers when we shut down.
for (PrefObserverMap::iterator it = pref_observers_.begin();
it != pref_observers_.end(); ++it) {
- NotificationObserverList::Iterator obs_iterator(*(it->second));
+ 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,
- content::NotificationObserver* obs) {
+ PrefObserver* obs) {
// Get the pref observer list associated with the path.
- NotificationObserverList* observer_list = NULL;
+ PrefObserverList* observer_list = NULL;
const PrefObserverMap::iterator observer_iterator =
pref_observers_.find(path);
if (observer_iterator == pref_observers_.end()) {
- observer_list = new NotificationObserverList;
+ observer_list = new PrefObserverList;
pref_observers_[path] = observer_list;
} else {
observer_list = observer_iterator->second;
}
- // Verify that this observer doesn't already exist.
- NotificationObserverList::Iterator it(*observer_list);
- content::NotificationObserver* existing_obs;
- while ((existing_obs = it.GetNext()) != NULL) {
- DCHECK(existing_obs != obs) << path << " observer already registered";
- if (existing_obs == obs)
- return;
- }
-
- // Ok, safe to add the pref observer.
+ // Add the pref observer. ObserverList will DCHECK if it already is
+ // in the list.
observer_list->AddObserver(obs);
}
void PrefNotifierImpl::RemovePrefObserver(const char* path,
- content::NotificationObserver* obs) {
+ PrefObserver* obs) {
DCHECK(CalledOnValidThread());
const PrefObserverMap::iterator observer_iterator =
@@ -72,10 +66,14 @@
return;
}
- NotificationObserverList* observer_list = observer_iterator->second;
+ 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);
}
@@ -83,10 +81,17 @@
void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
DCHECK(CalledOnValidThread());
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PREF_INITIALIZATION_COMPLETED,
- content::Source<PrefService>(pref_service_),
- content::Details<bool>(&succeeded));
+ // 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) {
@@ -101,13 +106,9 @@
if (observer_iterator == pref_observers_.end())
return;
- NotificationObserverList::Iterator it(*(observer_iterator->second));
- content::NotificationObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- observer->Observe(chrome::NOTIFICATION_PREF_CHANGED,
- content::Source<PrefService>(pref_service_),
- content::Details<const std::string>(&path));
- }
+ FOR_EACH_OBSERVER(PrefObserver,
+ *(observer_iterator->second),
+ OnPreferenceChanged(pref_service_, path));
}
void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {