observer_list_internal.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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.
  4. #ifndef BASE_OBSERVER_LIST_INTERNAL_H_
  5. #define BASE_OBSERVER_LIST_INTERNAL_H_
  6. #include <string>
  7. #include "base/base_export.h"
  8. #include "base/check.h"
  9. #include "base/containers/linked_list.h"
  10. #include "base/dcheck_is_on.h"
  11. #include "base/memory/raw_ptr_exclusion.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "base/observer_list_types.h"
  14. #if EXPENSIVE_DCHECKS_ARE_ON()
  15. #include "base/debug/stack_trace.h"
  16. #endif
  17. namespace base {
  18. namespace internal {
  19. // Adapter for putting raw pointers into an ObserverList<Foo>::Unchecked.
  20. class BASE_EXPORT UncheckedObserverAdapter {
  21. public:
  22. explicit UncheckedObserverAdapter(const void* observer)
  23. : ptr_(const_cast<void*>(observer)) {}
  24. UncheckedObserverAdapter(const UncheckedObserverAdapter&) = delete;
  25. UncheckedObserverAdapter& operator=(const UncheckedObserverAdapter&) = delete;
  26. UncheckedObserverAdapter(UncheckedObserverAdapter&& other) = default;
  27. UncheckedObserverAdapter& operator=(UncheckedObserverAdapter&& other) =
  28. default;
  29. void MarkForRemoval() { ptr_ = nullptr; }
  30. bool IsMarkedForRemoval() const { return !ptr_; }
  31. bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
  32. template <class ObserverType>
  33. static ObserverType* Get(const UncheckedObserverAdapter& adapter) {
  34. static_assert(
  35. !std::is_base_of<CheckedObserver, ObserverType>::value,
  36. "CheckedObserver classes must not use ObserverList<T>::Unchecked.");
  37. return static_cast<ObserverType*>(adapter.ptr_);
  38. }
  39. #if EXPENSIVE_DCHECKS_ARE_ON()
  40. std::string GetCreationStackString() const { return stack_.ToString(); }
  41. #endif // EXPENSIVE_DCHECKS_ARE_ON()
  42. private:
  43. void* ptr_;
  44. #if EXPENSIVE_DCHECKS_ARE_ON()
  45. base::debug::StackTrace stack_;
  46. #endif // EXPENSIVE_DCHECKS_ARE_ON()
  47. };
  48. // Adapter for CheckedObserver types so that they can use the same syntax as a
  49. // raw pointer when stored in the std::vector of observers in an ObserverList.
  50. // It wraps a WeakPtr<CheckedObserver> and allows a "null" pointer via
  51. // destruction to be distinguished from an observer marked for deferred removal
  52. // whilst an iteration is in progress.
  53. class BASE_EXPORT CheckedObserverAdapter {
  54. public:
  55. explicit CheckedObserverAdapter(const CheckedObserver* observer);
  56. // Move-only construction and assignment is required to store this in STL
  57. // types.
  58. CheckedObserverAdapter(CheckedObserverAdapter&& other);
  59. CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
  60. CheckedObserverAdapter(const CheckedObserverAdapter&) = delete;
  61. CheckedObserverAdapter& operator=(const CheckedObserverAdapter&) = delete;
  62. ~CheckedObserverAdapter();
  63. void MarkForRemoval() {
  64. DCHECK(weak_ptr_);
  65. weak_ptr_ = nullptr;
  66. }
  67. bool IsMarkedForRemoval() const {
  68. // If |weak_ptr_| was invalidated then this attempt to iterate over the
  69. // pointer is a UAF. Tip: If it's unclear where the `delete` occurred, try
  70. // adding CHECK(!IsInObserverList()) to the ~CheckedObserver() (destructor)
  71. // override. However, note that this is not always a bug: a destroyed
  72. // observer can exist in an ObserverList so long as nothing iterates over
  73. // the ObserverList before the list itself is destroyed.
  74. CHECK(!weak_ptr_.WasInvalidated());
  75. return weak_ptr_ == nullptr;
  76. }
  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;
  81. }
  82. template <class ObserverType>
  83. static ObserverType* Get(const CheckedObserverAdapter& adapter) {
  84. static_assert(
  85. std::is_base_of<CheckedObserver, ObserverType>::value,
  86. "Observers should inherit from base::CheckedObserver. "
  87. "Use ObserverList<T>::Unchecked to observe with raw pointers.");
  88. DCHECK(adapter.weak_ptr_);
  89. return static_cast<ObserverType*>(adapter.weak_ptr_.get());
  90. }
  91. #if EXPENSIVE_DCHECKS_ARE_ON()
  92. std::string GetCreationStackString() const { return stack_.ToString(); }
  93. #endif
  94. private:
  95. WeakPtr<CheckedObserver> weak_ptr_;
  96. #if EXPENSIVE_DCHECKS_ARE_ON()
  97. base::debug::StackTrace stack_;
  98. #endif
  99. };
  100. // Wraps a pointer in a stack-allocated, base::LinkNode. The node is
  101. // automatically removed from the linked list upon destruction (of the node, not
  102. // the pointer). Nodes are detached from the list via Invalidate() in the
  103. // destructor of ObserverList. This invalidates all WeakLinkNodes. There is no
  104. // threading support.
  105. template <class ObserverList>
  106. class WeakLinkNode : public base::LinkNode<WeakLinkNode<ObserverList>> {
  107. public:
  108. WeakLinkNode() = default;
  109. explicit WeakLinkNode(ObserverList* list) { SetList(list); }
  110. WeakLinkNode(const WeakLinkNode&) = delete;
  111. WeakLinkNode& operator=(const WeakLinkNode&) = delete;
  112. ~WeakLinkNode() { Invalidate(); }
  113. bool IsOnlyRemainingNode() const {
  114. return list_ &&
  115. list_->live_iterators_.head() == list_->live_iterators_.tail();
  116. }
  117. void SetList(ObserverList* list) {
  118. DCHECK(!list_);
  119. DCHECK(list);
  120. list_ = list;
  121. list_->live_iterators_.Append(this);
  122. }
  123. void Invalidate() {
  124. if (list_) {
  125. list_ = nullptr;
  126. this->RemoveFromList();
  127. }
  128. }
  129. ObserverList* get() const {
  130. if (list_)
  131. DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
  132. return list_;
  133. }
  134. ObserverList* operator->() const { return get(); }
  135. explicit operator bool() const { return get(); }
  136. private:
  137. // `list_` is not a raw_ptr<...> for performance reasons: on-stack pointer +
  138. // based on analysis of sampling profiler data and tab_search:top100:2020.
  139. RAW_PTR_EXCLUSION ObserverList* list_ = nullptr;
  140. };
  141. } // namespace internal
  142. } // namespace base
  143. #endif // BASE_OBSERVER_LIST_INTERNAL_H_