1 // Copyright 2018 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.
5 #ifndef BASE_OBSERVER_LIST_INTERNAL_H_
6 #define BASE_OBSERVER_LIST_INTERNAL_H_
8 #include "base/base_export.h"
9 #include "base/check_op.h"
10 #include "base/containers/linked_list.h"
11 #include "base/macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/observer_list_types.h"
18 // Adapter for putting raw pointers into an ObserverList<Foo>::Unchecked.
19 class BASE_EXPORT UncheckedObserverAdapter {
21 explicit UncheckedObserverAdapter(const void* observer)
22 : ptr_(const_cast<void*>(observer)) {}
23 UncheckedObserverAdapter(UncheckedObserverAdapter&& other) = default;
24 UncheckedObserverAdapter& operator=(UncheckedObserverAdapter&& other) =
27 void MarkForRemoval() { ptr_ = nullptr; }
29 bool IsMarkedForRemoval() const { return !ptr_; }
30 bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
32 template <class ObserverType>
33 static ObserverType* Get(const UncheckedObserverAdapter& adapter) {
35 !std::is_base_of<CheckedObserver, ObserverType>::value,
36 "CheckedObserver classes must not use ObserverList<T>::Unchecked.");
37 return static_cast<ObserverType*>(adapter.ptr_);
43 DISALLOW_COPY_AND_ASSIGN(UncheckedObserverAdapter);
46 // Adapter for CheckedObserver types so that they can use the same syntax as a
47 // raw pointer when stored in the std::vector of observers in an ObserverList.
48 // It wraps a WeakPtr<CheckedObserver> and allows a "null" pointer via
49 // destruction to be distinguished from an observer marked for deferred removal
50 // whilst an iteration is in progress.
51 class BASE_EXPORT CheckedObserverAdapter {
53 explicit CheckedObserverAdapter(const CheckedObserver* observer);
55 // Move-only construction and assignment is required to store this in STL
57 CheckedObserverAdapter(CheckedObserverAdapter&& other);
58 CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
59 ~CheckedObserverAdapter();
61 void MarkForRemoval() {
66 bool IsMarkedForRemoval() const {
67 // If |weak_ptr_| was invalidated then this attempt to iterate over the
68 // pointer is a UAF. Tip: If it's unclear where the `delete` occurred, try
69 // adding CHECK(!IsInObserverList()) to the ~CheckedObserver() (destructor)
70 // override. However, note that this is not always a bug: a destroyed
71 // observer can exist in an ObserverList so long as nothing iterates over
72 // the ObserverList before the list itself is destroyed.
73 CHECK(!weak_ptr_.WasInvalidated());
74 return weak_ptr_ == nullptr;
77 bool IsEqual(const CheckedObserver* rhs) const {
78 // Note that inside an iteration, ObserverList::HasObserver() may call this
79 // and |weak_ptr_| may be null due to a deferred removal, which is fine.
80 return weak_ptr_.get() == rhs;
83 template <class ObserverType>
84 static ObserverType* Get(const CheckedObserverAdapter& adapter) {
86 std::is_base_of<CheckedObserver, ObserverType>::value,
87 "Observers should inherit from base::CheckedObserver. "
88 "Use ObserverList<T>::Unchecked to observe with raw pointers.");
89 DCHECK(adapter.weak_ptr_);
90 return static_cast<ObserverType*>(adapter.weak_ptr_.get());
94 WeakPtr<CheckedObserver> weak_ptr_;
96 DISALLOW_COPY_AND_ASSIGN(CheckedObserverAdapter);
99 // Wraps a pointer in a stack-allocated, base::LinkNode. The node is
100 // automatically removed from the linked list upon destruction (of the node, not
101 // the pointer). Nodes are detached from the list via Invalidate() in the
102 // destructor of ObserverList. This invalidates all WeakLinkNodes. There is no
103 // threading support.
104 template <class ObserverList>
105 class WeakLinkNode : public base::LinkNode<WeakLinkNode<ObserverList>> {
107 WeakLinkNode() = default;
108 explicit WeakLinkNode(ObserverList* list) { SetList(list); }
110 ~WeakLinkNode() { Invalidate(); }
112 bool IsOnlyRemainingNode() const {
114 list_->live_iterators_.head() == list_->live_iterators_.tail();
117 void SetList(ObserverList* list) {
121 list_->live_iterators_.Append(this);
127 this->RemoveFromList();
131 ObserverList* get() const {
133 DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
136 ObserverList* operator->() const { return get(); }
137 explicit operator bool() const { return get(); }
140 ObserverList* list_ = nullptr;
142 DISALLOW_COPY_AND_ASSIGN(WeakLinkNode);
145 } // namespace internal
148 #endif // BASE_OBSERVER_LIST_INTERNAL_H_