1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/chrome/common/notification_service.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,143 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "chrome/common/notification_service.h" 1.9 + 1.10 +#include "base/lazy_instance.h" 1.11 +#include "base/thread_local.h" 1.12 + 1.13 +static base::LazyInstance<base::ThreadLocalPointer<NotificationService> > 1.14 + lazy_tls_ptr(base::LINKER_INITIALIZED); 1.15 + 1.16 +// static 1.17 +NotificationService* NotificationService::current() { 1.18 + return lazy_tls_ptr.Pointer()->Get(); 1.19 +} 1.20 + 1.21 +// static 1.22 +bool NotificationService::HasKey(const NotificationSourceMap& map, 1.23 + const NotificationSource& source) { 1.24 + return map.find(source.map_key()) != map.end(); 1.25 +} 1.26 + 1.27 +NotificationService::NotificationService() { 1.28 + DCHECK(current() == NULL); 1.29 +#ifndef NDEBUG 1.30 + memset(observer_counts_, 0, sizeof(observer_counts_)); 1.31 +#endif 1.32 + 1.33 + lazy_tls_ptr.Pointer()->Set(this); 1.34 +} 1.35 + 1.36 +void NotificationService::AddObserver(NotificationObserver* observer, 1.37 + NotificationType type, 1.38 + const NotificationSource& source) { 1.39 + DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT); 1.40 + 1.41 + // We have gotten some crashes where the observer pointer is NULL. The problem 1.42 + // is that this happens when we actually execute a notification, so have no 1.43 + // way of knowing who the bad observer was. We want to know when this happens 1.44 + // in release mode so we know what code to blame the crash on (since this is 1.45 + // guaranteed to crash later). 1.46 + CHECK(observer); 1.47 + 1.48 + NotificationObserverList* observer_list; 1.49 + if (HasKey(observers_[type.value], source)) { 1.50 + observer_list = observers_[type.value][source.map_key()]; 1.51 + } else { 1.52 + observer_list = new NotificationObserverList; 1.53 + observers_[type.value][source.map_key()] = observer_list; 1.54 + } 1.55 + 1.56 + observer_list->AddObserver(observer); 1.57 +#ifndef NDEBUG 1.58 + ++observer_counts_[type.value]; 1.59 +#endif 1.60 +} 1.61 + 1.62 +void NotificationService::RemoveObserver(NotificationObserver* observer, 1.63 + NotificationType type, 1.64 + const NotificationSource& source) { 1.65 + DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT); 1.66 + DCHECK(HasKey(observers_[type.value], source)); 1.67 + 1.68 + NotificationObserverList* observer_list = 1.69 + observers_[type.value][source.map_key()]; 1.70 + if (observer_list) { 1.71 + observer_list->RemoveObserver(observer); 1.72 +#ifndef NDEBUG 1.73 + --observer_counts_[type.value]; 1.74 +#endif 1.75 + } 1.76 + 1.77 + // TODO(jhughes): Remove observer list from map if empty? 1.78 +} 1.79 + 1.80 +void NotificationService::Notify(NotificationType type, 1.81 + const NotificationSource& source, 1.82 + const NotificationDetails& details) { 1.83 + DCHECK(type.value > NotificationType::ALL) << 1.84 + "Allowed for observing, but not posting."; 1.85 + DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT); 1.86 + 1.87 + // There's no particular reason for the order in which the different 1.88 + // classes of observers get notified here. 1.89 + 1.90 + // Notify observers of all types and all sources 1.91 + if (HasKey(observers_[NotificationType::ALL], AllSources()) && 1.92 + source != AllSources()) { 1.93 + FOR_EACH_OBSERVER(NotificationObserver, 1.94 + *observers_[NotificationType::ALL][AllSources().map_key()], 1.95 + Observe(type, source, details)); 1.96 + } 1.97 + 1.98 + // Notify observers of all types and the given source 1.99 + if (HasKey(observers_[NotificationType::ALL], source)) { 1.100 + FOR_EACH_OBSERVER(NotificationObserver, 1.101 + *observers_[NotificationType::ALL][source.map_key()], 1.102 + Observe(type, source, details)); 1.103 + } 1.104 + 1.105 + // Notify observers of the given type and all sources 1.106 + if (HasKey(observers_[type.value], AllSources()) && 1.107 + source != AllSources()) { 1.108 + FOR_EACH_OBSERVER(NotificationObserver, 1.109 + *observers_[type.value][AllSources().map_key()], 1.110 + Observe(type, source, details)); 1.111 + } 1.112 + 1.113 + // Notify observers of the given type and the given source 1.114 + if (HasKey(observers_[type.value], source)) { 1.115 + FOR_EACH_OBSERVER(NotificationObserver, 1.116 + *observers_[type.value][source.map_key()], 1.117 + Observe(type, source, details)); 1.118 + } 1.119 +} 1.120 + 1.121 + 1.122 +NotificationService::~NotificationService() { 1.123 + lazy_tls_ptr.Pointer()->Set(NULL); 1.124 + 1.125 +#ifndef NDEBUG 1.126 + for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) { 1.127 + if (observer_counts_[i] > 0) { 1.128 + // This may not be completely fixable -- see 1.129 + // http://code.google.com/p/chromium/issues/detail?id=11010 . 1.130 + // But any new leaks should be fixed. 1.131 + CHROMIUM_LOG(WARNING) << observer_counts_[i] << " notification observer(s) leaked" 1.132 + << " of notification type " << i; 1.133 + } 1.134 + } 1.135 +#endif 1.136 + 1.137 + for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) { 1.138 + NotificationSourceMap omap = observers_[i]; 1.139 + for (NotificationSourceMap::iterator it = omap.begin(); 1.140 + it != omap.end(); ++it) { 1.141 + delete it->second; 1.142 + } 1.143 + } 1.144 +} 1.145 + 1.146 +NotificationObserver::~NotificationObserver() {}