LCOV - code coverage report
Current view: directory - ipc/chromium/src/chrome/common - notification_service.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 56 18 32.1 %
Date: 2012-06-02 Functions: 12 5 41.7 %

       1                 : // Copyright (c) 2006-2008 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/common/notification_service.h"
       6                 : 
       7                 : #include "base/lazy_instance.h"
       8                 : #include "base/thread_local.h"
       9                 : 
      10                 : static base::LazyInstance<base::ThreadLocalPointer<NotificationService> >
      11            1464 :     lazy_tls_ptr(base::LINKER_INITIALIZED);
      12                 : 
      13                 : // static
      14            1420 : NotificationService* NotificationService::current() {
      15            1420 :   return lazy_tls_ptr.Pointer()->Get();
      16                 : }
      17                 : 
      18                 : // static
      19               0 : bool NotificationService::HasKey(const NotificationSourceMap& map,
      20                 :                                  const NotificationSource& source) {
      21               0 :   return map.find(source.map_key()) != map.end();
      22                 : }
      23                 : 
      24            1420 : NotificationService::NotificationService() {
      25            1420 :   DCHECK(current() == NULL);
      26                 : #ifndef NDEBUG
      27            1420 :   memset(observer_counts_, 0, sizeof(observer_counts_));
      28                 : #endif
      29                 : 
      30            1420 :   lazy_tls_ptr.Pointer()->Set(this);
      31            1420 : }
      32                 : 
      33               0 : void NotificationService::AddObserver(NotificationObserver* observer,
      34                 :                                       NotificationType type,
      35                 :                                       const NotificationSource& source) {
      36               0 :   DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
      37                 : 
      38                 :   // We have gotten some crashes where the observer pointer is NULL. The problem
      39                 :   // is that this happens when we actually execute a notification, so have no
      40                 :   // way of knowing who the bad observer was. We want to know when this happens
      41                 :   // in release mode so we know what code to blame the crash on (since this is
      42                 :   // guaranteed to crash later).
      43               0 :   CHECK(observer);
      44                 : 
      45                 :   NotificationObserverList* observer_list;
      46               0 :   if (HasKey(observers_[type.value], source)) {
      47               0 :     observer_list = observers_[type.value][source.map_key()];
      48                 :   } else {
      49               0 :     observer_list = new NotificationObserverList;
      50               0 :     observers_[type.value][source.map_key()] = observer_list;
      51                 :   }
      52                 : 
      53               0 :   observer_list->AddObserver(observer);
      54                 : #ifndef NDEBUG
      55               0 :   ++observer_counts_[type.value];
      56                 : #endif
      57               0 : }
      58                 : 
      59               0 : void NotificationService::RemoveObserver(NotificationObserver* observer,
      60                 :                                          NotificationType type,
      61                 :                                          const NotificationSource& source) {
      62               0 :   DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
      63               0 :   DCHECK(HasKey(observers_[type.value], source));
      64                 : 
      65                 :   NotificationObserverList* observer_list =
      66               0 :       observers_[type.value][source.map_key()];
      67               0 :   if (observer_list) {
      68               0 :     observer_list->RemoveObserver(observer);
      69                 : #ifndef NDEBUG
      70               0 :     --observer_counts_[type.value];
      71                 : #endif
      72                 :   }
      73                 : 
      74                 :   // TODO(jhughes): Remove observer list from map if empty?
      75               0 : }
      76                 : 
      77               0 : void NotificationService::Notify(NotificationType type,
      78                 :                                  const NotificationSource& source,
      79                 :                                  const NotificationDetails& details) {
      80               0 :   DCHECK(type.value > NotificationType::ALL) <<
      81               0 :       "Allowed for observing, but not posting.";
      82               0 :   DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
      83                 : 
      84                 :   // There's no particular reason for the order in which the different
      85                 :   // classes of observers get notified here.
      86                 : 
      87                 :   // Notify observers of all types and all sources
      88               0 :   if (HasKey(observers_[NotificationType::ALL], AllSources()) &&
      89               0 :       source != AllSources()) {
      90               0 :     FOR_EACH_OBSERVER(NotificationObserver,
      91                 :        *observers_[NotificationType::ALL][AllSources().map_key()],
      92                 :        Observe(type, source, details));
      93                 :   }
      94                 : 
      95                 :   // Notify observers of all types and the given source
      96               0 :   if (HasKey(observers_[NotificationType::ALL], source)) {
      97               0 :     FOR_EACH_OBSERVER(NotificationObserver,
      98                 :         *observers_[NotificationType::ALL][source.map_key()],
      99                 :         Observe(type, source, details));
     100                 :   }
     101                 : 
     102                 :   // Notify observers of the given type and all sources
     103               0 :   if (HasKey(observers_[type.value], AllSources()) &&
     104               0 :       source != AllSources()) {
     105               0 :     FOR_EACH_OBSERVER(NotificationObserver,
     106                 :                       *observers_[type.value][AllSources().map_key()],
     107                 :                       Observe(type, source, details));
     108                 :   }
     109                 : 
     110                 :   // Notify observers of the given type and the given source
     111               0 :   if (HasKey(observers_[type.value], source)) {
     112               0 :     FOR_EACH_OBSERVER(NotificationObserver,
     113                 :                       *observers_[type.value][source.map_key()],
     114                 :                       Observe(type, source, details));
     115                 :   }
     116               0 : }
     117                 : 
     118                 : 
     119          129129 : NotificationService::~NotificationService() {
     120            1419 :   lazy_tls_ptr.Pointer()->Set(NULL);
     121                 : 
     122                 : #ifndef NDEBUG
     123          126291 :   for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
     124          124872 :     if (observer_counts_[i] > 0) {
     125                 :       // This may not be completely fixable -- see
     126                 :       // http://code.google.com/p/chromium/issues/detail?id=11010 .
     127                 :       // But any new leaks should be fixed.
     128               0 :       LOG(WARNING) << observer_counts_[i] << " notification observer(s) leaked"
     129               0 :           << " of notification type " << i;
     130                 :     }
     131                 :   }
     132                 : #endif
     133                 : 
     134          126291 :   for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
     135          249744 :     NotificationSourceMap omap = observers_[i];
     136          249744 :     for (NotificationSourceMap::iterator it = omap.begin();
     137          124872 :          it != omap.end(); ++it) {
     138               0 :       delete it->second;
     139                 :     }
     140                 :   }
     141          127710 : }
     142                 : 
     143            4392 : NotificationObserver::~NotificationObserver() {}

Generated by: LCOV version 1.7