Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: base/observer_list.h

Issue 7127001: Fix user-after-free error with ObserverList. The problem is that if an ObserverListBase::Iterato... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_OBSERVER_LIST_H__ 5 #ifndef BASE_OBSERVER_LIST_H__
6 #define BASE_OBSERVER_LIST_H__ 6 #define BASE_OBSERVER_LIST_H__
7 #pragma once 7 #pragma once
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/basictypes.h" 13 #include "base/basictypes.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h"
15 16
16 /////////////////////////////////////////////////////////////////////////////// 17 ///////////////////////////////////////////////////////////////////////////////
17 // 18 //
18 // OVERVIEW: 19 // OVERVIEW:
19 // 20 //
20 // A container for a list of observers. Unlike a normal STL vector or list, 21 // A container for a list of observers. Unlike a normal STL vector or list,
21 // this container can be modified during iteration without invalidating the 22 // this container can be modified during iteration without invalidating the
22 // iterator. So, it safely handles the case of an observer removing itself 23 // iterator. So, it safely handles the case of an observer removing itself
23 // or other observers from the list while observers are being notified. 24 // or other observers from the list while observers are being notified.
24 // 25 //
(...skipping 29 matching lines...) Expand all
54 // ObserverList<Observer> observer_list_; 55 // ObserverList<Observer> observer_list_;
55 // }; 56 // };
56 // 57 //
57 // 58 //
58 /////////////////////////////////////////////////////////////////////////////// 59 ///////////////////////////////////////////////////////////////////////////////
59 60
60 template <typename ObserverType> 61 template <typename ObserverType>
61 class ObserverListThreadSafe; 62 class ObserverListThreadSafe;
62 63
63 template <class ObserverType> 64 template <class ObserverType>
64 class ObserverListBase { 65 class ObserverListBase
66 : public base::SupportsWeakPtr<ObserverListBase<ObserverType> > {
65 public: 67 public:
66 // Enumeration of which observers are notified. 68 // Enumeration of which observers are notified.
67 enum NotificationType { 69 enum NotificationType {
68 // Specifies that any observers added during notification are notified. 70 // Specifies that any observers added during notification are notified.
69 // This is the default type if non type is provided to the constructor. 71 // This is the default type if non type is provided to the constructor.
70 NOTIFY_ALL, 72 NOTIFY_ALL,
71 73
72 // Specifies that observers added while sending out notification are not 74 // Specifies that observers added while sending out notification are not
73 // notified. 75 // notified.
74 NOTIFY_EXISTING_ONLY 76 NOTIFY_EXISTING_ONLY
75 }; 77 };
76 78
77 // An iterator class that can be used to access the list of observers. See 79 // An iterator class that can be used to access the list of observers. See
78 // also the FOR_EACH_OBSERVER macro defined below. 80 // also the FOR_EACH_OBSERVER macro defined below.
79 class Iterator { 81 class Iterator {
80 public: 82 public:
81 Iterator(ObserverListBase<ObserverType>& list) 83 Iterator(ObserverListBase<ObserverType>& list)
82 : list_(list), 84 : list_(list.AsWeakPtr()),
83 index_(0), 85 index_(0),
84 max_index_(list.type_ == NOTIFY_ALL ? 86 max_index_(list.type_ == NOTIFY_ALL ?
85 std::numeric_limits<size_t>::max() : 87 std::numeric_limits<size_t>::max() :
86 list.observers_.size()) { 88 list.observers_.size()) {
87 ++list_.notify_depth_; 89 ++list_->notify_depth_;
88 } 90 }
89 91
90 ~Iterator() { 92 ~Iterator() {
91 if (--list_.notify_depth_ == 0) 93 if (list_ && --list_->notify_depth_ == 0)
92 list_.Compact(); 94 list_->Compact();
93 } 95 }
94 96
95 ObserverType* GetNext() { 97 ObserverType* GetNext() {
96 ListType& observers = list_.observers_; 98 if (!list_)
99 return NULL;
100 ListType& observers = list_->observers_;
97 // Advance if the current element is null 101 // Advance if the current element is null
98 size_t max_index = std::min(max_index_, observers.size()); 102 size_t max_index = std::min(max_index_, observers.size());
99 while (index_ < max_index && !observers[index_]) 103 while (index_ < max_index && !observers[index_])
100 ++index_; 104 ++index_;
101 return index_ < max_index ? observers[index_++] : NULL; 105 return index_ < max_index ? observers[index_++] : NULL;
102 } 106 }
103 107
104 private: 108 private:
105 ObserverListBase<ObserverType>& list_; 109 base::WeakPtr<ObserverListBase<ObserverType> > list_;
106 size_t index_; 110 size_t index_;
107 size_t max_index_; 111 size_t max_index_;
108 }; 112 };
109 113
110 ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {} 114 ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {}
111 explicit ObserverListBase(NotificationType type) 115 explicit ObserverListBase(NotificationType type)
112 : notify_depth_(0), type_(type) {} 116 : notify_depth_(0), type_(type) {}
113 117
114 // Add an observer to the list. An observer should not be added to 118 // Add an observer to the list. An observer should not be added to
115 // the same list more than once. 119 // the same list more than once.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 207
204 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ 208 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \
205 do { \ 209 do { \
206 ObserverListBase<ObserverType>::Iterator it(observer_list); \ 210 ObserverListBase<ObserverType>::Iterator it(observer_list); \
207 ObserverType* obs; \ 211 ObserverType* obs; \
208 while ((obs = it.GetNext()) != NULL) \ 212 while ((obs = it.GetNext()) != NULL) \
209 obs->func; \ 213 obs->func; \
210 } while (0) 214 } while (0)
211 215
212 #endif // BASE_OBSERVER_LIST_H__ 216 #endif // BASE_OBSERVER_LIST_H__
OLDNEW
« no previous file with comments | « no previous file | base/observer_list_unittest.cc » ('j') | content/browser/renderer_host/render_view_host.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698