[M85 Dev][EFL] Fix crashes at webview launch
[platform/framework/web/chromium-efl.git] / base / observer_list_internal.h
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
5 #ifndef BASE_OBSERVER_LIST_INTERNAL_H_
6 #define BASE_OBSERVER_LIST_INTERNAL_H_
7
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"
14
15 namespace base {
16 namespace internal {
17
18 // Adapter for putting raw pointers into an ObserverList<Foo>::Unchecked.
19 class BASE_EXPORT UncheckedObserverAdapter {
20  public:
21   explicit UncheckedObserverAdapter(const void* observer)
22       : ptr_(const_cast<void*>(observer)) {}
23   UncheckedObserverAdapter(UncheckedObserverAdapter&& other) = default;
24   UncheckedObserverAdapter& operator=(UncheckedObserverAdapter&& other) =
25       default;
26
27   void MarkForRemoval() { ptr_ = nullptr; }
28
29   bool IsMarkedForRemoval() const { return !ptr_; }
30   bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
31
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
40  private:
41   void* ptr_;
42
43   DISALLOW_COPY_AND_ASSIGN(UncheckedObserverAdapter);
44 };
45
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 {
52  public:
53   explicit CheckedObserverAdapter(const CheckedObserver* observer);
54
55   // Move-only construction and assignment is required to store this in STL
56   // types.
57   CheckedObserverAdapter(CheckedObserverAdapter&& other);
58   CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
59   ~CheckedObserverAdapter();
60
61   void MarkForRemoval() {
62     DCHECK(weak_ptr_);
63     weak_ptr_ = nullptr;
64   }
65
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;
75   }
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
83   template <class ObserverType>
84   static ObserverType* Get(const CheckedObserverAdapter& adapter) {
85     static_assert(
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());
91   }
92
93  private:
94   WeakPtr<CheckedObserver> weak_ptr_;
95
96   DISALLOW_COPY_AND_ASSIGN(CheckedObserverAdapter);
97 };
98
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>> {
106  public:
107   WeakLinkNode() = default;
108   explicit WeakLinkNode(ObserverList* list) { SetList(list); }
109
110   ~WeakLinkNode() { Invalidate(); }
111
112   bool IsOnlyRemainingNode() const {
113     return list_ &&
114            list_->live_iterators_.head() == list_->live_iterators_.tail();
115   }
116
117   void SetList(ObserverList* list) {
118     DCHECK(!list_);
119     DCHECK(list);
120     list_ = list;
121     list_->live_iterators_.Append(this);
122   }
123
124   void Invalidate() {
125     if (list_) {
126       list_ = nullptr;
127       this->RemoveFromList();
128     }
129   }
130
131   ObserverList* get() const {
132     if (list_)
133       DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
134     return list_;
135   }
136   ObserverList* operator->() const { return get(); }
137   explicit operator bool() const { return get(); }
138
139  private:
140   ObserverList* list_ = nullptr;
141
142   DISALLOW_COPY_AND_ASSIGN(WeakLinkNode);
143 };
144
145 }  // namespace internal
146 }  // namespace base
147
148 #endif  // BASE_OBSERVER_LIST_INTERNAL_H_