fixup! [M120 Migration] Notify media device state to webbrowser
[platform/framework/web/chromium-efl.git] / base / observer_list_internal.h
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.
4
5 #ifndef BASE_OBSERVER_LIST_INTERNAL_H_
6 #define BASE_OBSERVER_LIST_INTERNAL_H_
7
8 #include <string>
9
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"
18
19 #if DCHECK_IS_ON()
20 #include "base/debug/stack_trace.h"
21 #endif
22
23 namespace base {
24 namespace internal {
25
26 // Adapter for putting raw pointers into an ObserverList<Foo>::Unchecked.
27 class BASE_EXPORT UncheckedObserverAdapter {
28  public:
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) =
35       default;
36
37   void MarkForRemoval() { ptr_ = nullptr; }
38
39   bool IsMarkedForRemoval() const { return !ptr_; }
40   bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
41
42   template <class ObserverType>
43   static ObserverType* Get(const UncheckedObserverAdapter& adapter) {
44     static_assert(
45         !std::is_base_of_v<CheckedObserver, ObserverType>,
46         "CheckedObserver classes must not use ObserverList<T>::Unchecked.");
47     return static_cast<ObserverType*>(adapter.ptr_);
48   }
49
50 #if DCHECK_IS_ON()
51   std::string GetCreationStackString() const {
52     return "Observer created at:\n" + stack_.ToString();
53   }
54 #endif  // DCHECK_IS_ON()
55
56  private:
57   raw_ptr<void, AcrossTasksDanglingUntriaged> ptr_;
58 #if DCHECK_IS_ON()
59   base::debug::StackTrace stack_;
60 #endif  // DCHECK_IS_ON()
61 };
62
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 {
69  public:
70   explicit CheckedObserverAdapter(const CheckedObserver* observer);
71
72   // Move-only construction and assignment is required to store this in STL
73   // types.
74   CheckedObserverAdapter(CheckedObserverAdapter&& other);
75   CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
76   CheckedObserverAdapter(const CheckedObserverAdapter&) = delete;
77   CheckedObserverAdapter& operator=(const CheckedObserverAdapter&) = delete;
78   ~CheckedObserverAdapter();
79
80   void MarkForRemoval() {
81     DCHECK(weak_ptr_);
82     weak_ptr_ = nullptr;
83   }
84
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;
94   }
95
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;
100   }
101
102   template <class ObserverType>
103   static ObserverType* Get(const CheckedObserverAdapter& adapter) {
104     static_assert(
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());
110   }
111
112 #if DCHECK_IS_ON()
113   std::string GetCreationStackString() const { return stack_.ToString(); }
114 #endif
115
116  private:
117   WeakPtr<CheckedObserver> weak_ptr_;
118 #if DCHECK_IS_ON()
119   base::debug::StackTrace stack_;
120 #endif
121 };
122
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>> {
130  public:
131   WeakLinkNode() = default;
132   explicit WeakLinkNode(ObserverList* list) { SetList(list); }
133   WeakLinkNode(const WeakLinkNode&) = delete;
134   WeakLinkNode& operator=(const WeakLinkNode&) = delete;
135
136   ~WeakLinkNode() { Invalidate(); }
137
138   bool IsOnlyRemainingNode() const {
139     return list_ &&
140            list_->live_iterators_.head() == list_->live_iterators_.tail();
141   }
142
143   void SetList(ObserverList* list) {
144     DCHECK(!list_);
145     DCHECK(list);
146     list_ = list;
147     list_->live_iterators_.Append(this);
148   }
149
150   void Invalidate() {
151     if (list_) {
152       list_ = nullptr;
153       this->RemoveFromList();
154     }
155   }
156
157   ObserverList* get() const {
158     if (list_)
159       DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
160     return list_;
161   }
162   ObserverList* operator->() const { return get(); }
163   explicit operator bool() const { return get(); }
164
165  private:
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;
169 };
170
171 }  // namespace internal
172 }  // namespace base
173
174 #endif  // BASE_OBSERVER_LIST_INTERNAL_H_