diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-19 23:17:07 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-19 23:17:07 +0000 |
commit | ad50def5e1165d0cc74b98f988bbd5962587d9f4 (patch) | |
tree | 3a751abaed2cc056ca60b8b1e3ff54532a6f4d3f /content/browser/notification_service_impl.cc | |
parent | 75c920505ddfb2d49c194c76bde64edd6b3f91f2 (diff) | |
download | chromium_src-ad50def5e1165d0cc74b98f988bbd5962587d9f4.zip chromium_src-ad50def5e1165d0cc74b98f988bbd5962587d9f4.tar.gz chromium_src-ad50def5e1165d0cc74b98f988bbd5962587d9f4.tar.bz2 |
Make NotificationService an interface in the content namespace, and switch callers to use it. Move the implementation to content/browser. Stop creating it in all child processes since it's only used in the browser.
BUG=98716
Review URL: http://codereview.chromium.org/8342048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106403 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/notification_service_impl.cc')
-rw-r--r-- | content/browser/notification_service_impl.cc | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/content/browser/notification_service_impl.cc b/content/browser/notification_service_impl.cc new file mode 100644 index 0000000..795cb30 --- /dev/null +++ b/content/browser/notification_service_impl.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2010 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 "content/browser/notification_service_impl.h" + +#include "base/lazy_instance.h" +#include "base/threading/thread_local.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_types.h" + +static base::LazyInstance<base::ThreadLocalPointer<NotificationServiceImpl> > + lazy_tls_ptr(base::LINKER_INITIALIZED); + +// static +NotificationServiceImpl* NotificationServiceImpl::current() { + return lazy_tls_ptr.Pointer()->Get(); +} + +// static +content::NotificationService* content::NotificationService::current() { + return NotificationServiceImpl::current(); +} + +// static +bool NotificationServiceImpl::HasKey(const NotificationSourceMap& map, + const content::NotificationSource& source) { + return map.find(source.map_key()) != map.end(); +} + +NotificationServiceImpl::NotificationServiceImpl() { + DCHECK(current() == NULL); + lazy_tls_ptr.Pointer()->Set(this); +} + +void NotificationServiceImpl::AddObserver( + content::NotificationObserver* observer, + int type, + const content::NotificationSource& source) { + // We have gotten some crashes where the observer pointer is NULL. The problem + // is that this happens when we actually execute a notification, so have no + // way of knowing who the bad observer was. We want to know when this happens + // in release mode so we know what code to blame the crash on (since this is + // guaranteed to crash later). + CHECK(observer); + + NotificationObserverList* observer_list; + if (HasKey(observers_[type], source)) { + observer_list = observers_[type][source.map_key()]; + } else { + observer_list = new NotificationObserverList; + observers_[type][source.map_key()] = observer_list; + } + + observer_list->AddObserver(observer); +#ifndef NDEBUG + ++observer_counts_[type]; +#endif +} + +void NotificationServiceImpl::RemoveObserver( + content::NotificationObserver* observer, + int type, + const content::NotificationSource& source) { + // This is a very serious bug. An object is most likely being deleted on + // the wrong thread, and as a result another thread's NotificationServiceImpl + // has its deleted pointer in its map. A garbge object will be called in the + // future. + // NOTE: when this check shows crashes, use BrowserThread::DeleteOnIOThread or + // other variants as the trait on the object. + CHECK(HasKey(observers_[type], source)); + + NotificationObserverList* observer_list = + observers_[type][source.map_key()]; + if (observer_list) { + observer_list->RemoveObserver(observer); +#ifndef NDEBUG + --observer_counts_[type]; +#endif + } + + // TODO(jhughes): Remove observer list from map if empty? +} + +void NotificationServiceImpl::Notify( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(type > content::NOTIFICATION_ALL) << + "Allowed for observing, but not posting."; + + // There's no particular reason for the order in which the different + // classes of observers get notified here. + + // Notify observers of all types and all sources + if (HasKey(observers_[content::NOTIFICATION_ALL], AllSources()) && + source != AllSources()) { + FOR_EACH_OBSERVER(content::NotificationObserver, + *observers_[content::NOTIFICATION_ALL][AllSources().map_key()], + Observe(type, source, details)); + } + + // Notify observers of all types and the given source + if (HasKey(observers_[content::NOTIFICATION_ALL], source)) { + FOR_EACH_OBSERVER(content::NotificationObserver, + *observers_[content::NOTIFICATION_ALL][source.map_key()], + Observe(type, source, details)); + } + + // Notify observers of the given type and all sources + if (HasKey(observers_[type], AllSources()) && + source != AllSources()) { + FOR_EACH_OBSERVER(content::NotificationObserver, + *observers_[type][AllSources().map_key()], + Observe(type, source, details)); + } + + // Notify observers of the given type and the given source + if (HasKey(observers_[type], source)) { + FOR_EACH_OBSERVER(content::NotificationObserver, + *observers_[type][source.map_key()], + Observe(type, source, details)); + } +} + + +NotificationServiceImpl::~NotificationServiceImpl() { + lazy_tls_ptr.Pointer()->Set(NULL); + +#ifndef NDEBUG + for (int i = 0; i < static_cast<int>(observer_counts_.size()); i++) { + if (observer_counts_[i] > 0) { + // This may not be completely fixable -- see + // http://code.google.com/p/chromium/issues/detail?id=11010 . + VLOG(1) << observer_counts_[i] << " notification observer(s) leaked " + "of notification type " << i; + } + } +#endif + + for (int i = 0; i < static_cast<int>(observers_.size()); i++) { + NotificationSourceMap omap = observers_[i]; + for (NotificationSourceMap::iterator it = omap.begin(); + it != omap.end(); ++it) + delete it->second; + } +} |