observer_list_internal.h 5.0 KB

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