Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / base / scoped_observation.h
1 // Copyright 2020 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_SCOPED_OBSERVATION_H_
6 #define BASE_SCOPED_OBSERVATION_H_
7
8 #include <utility>
9
10 #include "base/check.h"
11 #include "base/check_op.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/scoped_observation_traits.h"
14
15 namespace base {
16
17 // `ScopedObservation` is used to keep track of a singular observation, i.e.,
18 // where an observer observes a single source only. Use
19 // `base::ScopedMultiSourceObservation` for objects that observe multiple
20 // sources.
21 //
22 // When a `ScopedObservation` is destroyed, it unregisters the observer from the
23 // observable if it was currently observing something. Otherwise it does
24 // nothing.
25 //
26 // Using a `ScopedObservation` instead of manually observing and unobserving has
27 // the following benefits:
28 // - The observer cannot accidentally forget to stop observing when it is
29 //   destroyed.
30 // - By calling `Reset`, an ongoing observation can be stopped before the
31 //   `ScopedObservation` is destroyed. If nothing was currently observed, then
32 //   calling `Reset` does nothing. This can be useful for when the observable is
33 //   destroyed before the observer is destroyed, because it prevents the
34 //   observer from accidentally unregistering itself from the destroyed
35 //   observable a second time when it itself is destroyed. Without
36 //   `ScopedObservation`, one might need to keep track of whether one has
37 //   already stopped observing in a separate boolean.
38 //
39 // A complete usage example can be found below.
40 //
41 // `observer.h`:
42 //   class Observer {
43 //    public:
44 //     virtual ~Observer() {}
45 //
46 //     virtual void OnEvent() {}
47 //   };
48 //
49 // `source.h`:
50 //   class Observer;
51 //   class Source {
52 //    public:
53 //     void AddObserver(Observer* observer);
54 //     void RemoveObserver(Observer* observer);
55 //   };
56 //
57 // `observer_impl.h`:
58 //   #include "observer.h"
59 //
60 //   class Source;
61 //
62 //   class ObserverImpl: public Observer {
63 //    public:
64 //     ObserverImpl(Source* source);
65 //     // Note how there is no need to stop observing in the destructor.
66 //     ~ObserverImpl() override {}
67 //
68 //     void OnEvent() override {
69 //       ...
70 //     }
71 //
72 //    private:
73 //     // Note that |obs_| can be instantiated with forward-declared Source.
74 //     base::ScopedObservation<Source, Observer> obs_{this};
75 //   };
76 //
77 // `observer_impl.cc`:
78 //   #include "observer_impl.h"
79 //   #include "source.h"
80 //
81 //   ObserverImpl::ObserverImpl(Source* source) {
82 //     // After the call |this| starts listening to events from |source|.
83 //     obs_.Observe(source);
84 //   }
85 //
86 ////////////////////////////////////////////////////////////////////////////////
87 //
88 // By default `ScopedObservation` only works with sources that expose
89 // `AddObserver` and `RemoveObserver`. However, it's also possible to
90 // adapt it to custom function names (say `AddFoo` and `RemoveFoo` accordingly)
91 // by tailoring ScopedObservationTraits<> for the given Source and Observer --
92 // see `base/scoped_observation_traits.h` for details.
93 //
94
95 template <class Source, class Observer>
96 class ScopedObservation {
97  public:
98   explicit ScopedObservation(Observer* observer) : observer_(observer) {}
99   ScopedObservation(const ScopedObservation&) = delete;
100   ScopedObservation& operator=(const ScopedObservation&) = delete;
101   ~ScopedObservation() { Reset(); }
102
103   // Adds the object passed to the constructor as an observer on |source|.
104   // IsObserving() must be false.
105   void Observe(Source* source) {
106     DCHECK_EQ(source_, nullptr);
107     source_ = source;
108     Traits::AddObserver(source_, observer_);
109   }
110
111   // Remove the object passed to the constructor as an observer from |source_|
112   // if currently observing. Does nothing otherwise.
113   void Reset() {
114     if (source_) {
115       Traits::RemoveObserver(std::exchange(source_, nullptr), observer_);
116     }
117   }
118
119   // Returns true if any source is being observed.
120   bool IsObserving() const { return source_ != nullptr; }
121
122   // Returns true if |source| is being observed.
123   bool IsObservingSource(Source* source) const {
124     DCHECK(source);
125     return source_ == source;
126   }
127
128   // Gets a pointer to the observed source, or nullptr if no source is being
129   // observed.
130   Source* GetSource() { return source_; }
131   const Source* GetSource() const { return source_; }
132
133  private:
134   using Traits = ScopedObservationTraits<Source, Observer>;
135
136   const raw_ptr<Observer, DanglingUntriaged> observer_;
137
138   // The observed source, if any.
139   raw_ptr<Source, LeakedDanglingUntriaged> source_ = nullptr;
140 };
141
142 }  // namespace base
143
144 #endif  // BASE_SCOPED_OBSERVATION_H_