1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_OBSERVER_LIST_INTERNAL_H_
6 #define BASE_OBSERVER_LIST_INTERNAL_H_
10 #include "base/base_export.h"
11 #include "base/check.h"
12 #include "base/containers/linked_list.h"
13 #include "base/dcheck_is_on.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/raw_ptr_exclusion.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/observer_list_types.h"
20 #include "base/debug/stack_trace.h"
26 // Adapter for putting raw pointers into an ObserverList<Foo>::Unchecked.
27 class BASE_EXPORT UncheckedObserverAdapter {
29 explicit UncheckedObserverAdapter(const void* observer)
30 : ptr_(const_cast<void*>(observer)) {}
31 UncheckedObserverAdapter(const UncheckedObserverAdapter&) = delete;
32 UncheckedObserverAdapter& operator=(const UncheckedObserverAdapter&) = delete;
33 UncheckedObserverAdapter(UncheckedObserverAdapter&& other) = default;
34 UncheckedObserverAdapter& operator=(UncheckedObserverAdapter&& other) =
37 void MarkForRemoval() { ptr_ = nullptr; }
39 bool IsMarkedForRemoval() const { return !ptr_; }
40 bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
42 template <class ObserverType>
43 static ObserverType* Get(const UncheckedObserverAdapter& adapter) {
45 !std::is_base_of_v<CheckedObserver, ObserverType>,
46 "CheckedObserver classes must not use ObserverList<T>::Unchecked.");
47 return static_cast<ObserverType*>(adapter.ptr_);
51 std::string GetCreationStackString() const {
52 return "Observer created at:\n" + stack_.ToString();
54 #endif // DCHECK_IS_ON()
57 raw_ptr<void, AcrossTasksDanglingUntriaged> ptr_;
59 base::debug::StackTrace stack_;
60 #endif // DCHECK_IS_ON()
63 // Adapter for CheckedObserver types so that they can use the same syntax as a
64 // raw pointer when stored in the std::vector of observers in an ObserverList.
65 // It wraps a WeakPtr<CheckedObserver> and allows a "null" pointer via
66 // destruction to be distinguished from an observer marked for deferred removal
67 // whilst an iteration is in progress.
68 class BASE_EXPORT CheckedObserverAdapter {
70 explicit CheckedObserverAdapter(const CheckedObserver* observer);
72 // Move-only construction and assignment is required to store this in STL
74 CheckedObserverAdapter(CheckedObserverAdapter&& other);
75 CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
76 CheckedObserverAdapter(const CheckedObserverAdapter&) = delete;
77 CheckedObserverAdapter& operator=(const CheckedObserverAdapter&) = delete;
78 ~CheckedObserverAdapter();
80 void MarkForRemoval() {
85 bool IsMarkedForRemoval() const {
86 // If |weak_ptr_| was invalidated then this attempt to iterate over the
87 // pointer is a UAF. Tip: If it's unclear where the `delete` occurred, try
88 // adding CHECK(!IsInObserverList()) to the ~CheckedObserver() (destructor)
89 // override. However, note that this is not always a bug: a destroyed
90 // observer can exist in an ObserverList so long as nothing iterates over
91 // the ObserverList before the list itself is destroyed.
92 CHECK(!weak_ptr_.WasInvalidated());
93 return weak_ptr_ == nullptr;
96 bool IsEqual(const CheckedObserver* rhs) const {
97 // Note that inside an iteration, ObserverList::HasObserver() may call this
98 // and |weak_ptr_| may be null due to a deferred removal, which is fine.
99 return weak_ptr_.get() == rhs;
102 template <class ObserverType>
103 static ObserverType* Get(const CheckedObserverAdapter& adapter) {
105 std::is_base_of_v<CheckedObserver, ObserverType>,
106 "Observers should inherit from base::CheckedObserver. "
107 "Use ObserverList<T>::Unchecked to observe with raw pointers.");
108 DCHECK(adapter.weak_ptr_);
109 return static_cast<ObserverType*>(adapter.weak_ptr_.get());
113 std::string GetCreationStackString() const { return stack_.ToString(); }
117 WeakPtr<CheckedObserver> weak_ptr_;
119 base::debug::StackTrace stack_;
123 // Wraps a pointer in a stack-allocated, base::LinkNode. The node is
124 // automatically removed from the linked list upon destruction (of the node, not
125 // the pointer). Nodes are detached from the list via Invalidate() in the
126 // destructor of ObserverList. This invalidates all WeakLinkNodes. There is no
127 // threading support.
128 template <class ObserverList>
129 class WeakLinkNode : public base::LinkNode<WeakLinkNode<ObserverList>> {
131 WeakLinkNode() = default;
132 explicit WeakLinkNode(ObserverList* list) { SetList(list); }
133 WeakLinkNode(const WeakLinkNode&) = delete;
134 WeakLinkNode& operator=(const WeakLinkNode&) = delete;
136 ~WeakLinkNode() { Invalidate(); }
138 bool IsOnlyRemainingNode() const {
140 list_->live_iterators_.head() == list_->live_iterators_.tail();
143 void SetList(ObserverList* list) {
147 list_->live_iterators_.Append(this);
153 this->RemoveFromList();
157 ObserverList* get() const {
159 DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
162 ObserverList* operator->() const { return get(); }
163 explicit operator bool() const { return get(); }
166 // `list_` is not a raw_ptr<...> for performance reasons: on-stack pointer +
167 // based on analysis of sampling profiler data and tab_search:top100:2020.
168 RAW_PTR_EXCLUSION ObserverList* list_ = nullptr;
171 } // namespace internal
174 #endif // BASE_OBSERVER_LIST_INTERNAL_H_