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_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
6 #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
7 
8 #include "base/base_export.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_refptr.h"
11 #include "base/message_loop/message_pump_for_io.h"
12 #include "base/message_loop/message_pump_for_ui.h"
13 #include "base/pending_task.h"
14 #include "base/single_thread_task_runner.h"
15 #include "build/build_config.h"
16 
17 namespace base {
18 
19 class MessageLoop;
20 
21 // MessageLoopCurrent is a proxy to the public interface of the MessageLoop
22 // bound to the thread it's obtained on.
23 //
24 // MessageLoopCurrent(ForUI|ForIO) is available statically through
25 // MessageLoopCurrent(ForUI|ForIO)::Get() on threads that have a matching
26 // MessageLoop instance. APIs intended for all consumers on the thread should be
27 // on MessageLoopCurrent(ForUI|ForIO), while APIs intended for the owner of the
28 // instance should be on MessageLoop(ForUI|ForIO).
29 //
30 // Why: Historically MessageLoop::current() gave access to the full MessageLoop
31 // API, preventing both addition of powerful owner-only APIs as well as making
32 // it harder to remove callers of deprecated APIs (that need to stick around for
33 // a few owner-only use cases and re-accrue callers after cleanup per remaining
34 // publicly available).
35 //
36 // As such, many methods below are flagged as deprecated and should be removed
37 // (or moved back to MessageLoop) once all static callers have been migrated.
38 class BASE_EXPORT MessageLoopCurrent {
39  public:
40   // MessageLoopCurrent is effectively just a disguised pointer and is fine to
41   // copy around.
42   MessageLoopCurrent(const MessageLoopCurrent& other) = default;
43   MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = default;
44 
45   // Returns a proxy object to interact with the MessageLoop running the
46   // current thread. It must only be used on the thread it was obtained.
47   static MessageLoopCurrent Get();
48 
49   // Returns true if the current thread is running a MessageLoop. Prefer this to
50   // verifying the boolean value of Get() (so that Get() can ultimately DCHECK
51   // it's only invoked when IsSet()).
52   static bool IsSet();
53 
54   // Allow MessageLoopCurrent to be used like a pointer to support the many
55   // callsites that used MessageLoop::current() that way when it was a
56   // MessageLoop*.
57   MessageLoopCurrent* operator->() { return this; }
58   explicit operator bool() const { return !!current_; }
59 
60   // TODO(gab): Migrate the types of variables that store MessageLoop::current()
61   // and remove this implicit cast back to MessageLoop*.
62   operator MessageLoop*() const { return current_; }
63 
64   // A DestructionObserver is notified when the current MessageLoop is being
65   // destroyed.  These observers are notified prior to MessageLoop::current()
66   // being changed to return NULL.  This gives interested parties the chance to
67   // do final cleanup that depends on the MessageLoop.
68   //
69   // NOTE: Any tasks posted to the MessageLoop during this notification will
70   // not be run.  Instead, they will be deleted.
71   //
72   // Deprecation note: Prefer SequenceLocalStorageSlot<std::unique_ptr<Foo>> to
73   // DestructionObserver to bind an object's lifetime to the current
74   // thread/sequence.
75   class BASE_EXPORT DestructionObserver {
76    public:
77     virtual void WillDestroyCurrentMessageLoop() = 0;
78 
79    protected:
80     virtual ~DestructionObserver() = default;
81   };
82 
83   // Add a DestructionObserver, which will start receiving notifications
84   // immediately.
85   void AddDestructionObserver(DestructionObserver* destruction_observer);
86 
87   // Remove a DestructionObserver.  It is safe to call this method while a
88   // DestructionObserver is receiving a notification callback.
89   void RemoveDestructionObserver(DestructionObserver* destruction_observer);
90 
91   // Forwards to MessageLoop::task_runner().
92   // DEPRECATED(https://crbug.com/616447): Use ThreadTaskRunnerHandle::Get()
93   // instead of MessageLoopCurrent::Get()->task_runner().
94   const scoped_refptr<SingleThreadTaskRunner>& task_runner() const;
95 
96   // Forwards to MessageLoop::SetTaskRunner().
97   // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop
98   // instance should replace its TaskRunner.
99   void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
100 
101   // A TaskObserver is an object that receives task notifications from the
102   // MessageLoop.
103   //
104   // NOTE: A TaskObserver implementation should be extremely fast!
105   class BASE_EXPORT TaskObserver {
106    public:
107     // This method is called before processing a task.
108     virtual void WillProcessTask(const PendingTask& pending_task) = 0;
109 
110     // This method is called after processing a task.
111     virtual void DidProcessTask(const PendingTask& pending_task) = 0;
112 
113    protected:
114     virtual ~TaskObserver() = default;
115   };
116 
117   // Forwards to MessageLoop::(Add|Remove)TaskObserver.
118   // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop
119   // instance should add task observers on it.
120   void AddTaskObserver(TaskObserver* task_observer);
121   void RemoveTaskObserver(TaskObserver* task_observer);
122 
123   // Enables or disables the recursive task processing. This happens in the case
124   // of recursive message loops. Some unwanted message loops may occur when
125   // using common controls or printer functions. By default, recursive task
126   // processing is disabled.
127   //
128   // Please use |ScopedNestableTaskAllower| instead of calling these methods
129   // directly.  In general, nestable message loops are to be avoided.  They are
130   // dangerous and difficult to get right, so please use with extreme caution.
131   //
132   // The specific case where tasks get queued is:
133   // - The thread is running a message loop.
134   // - It receives a task #1 and executes it.
135   // - The task #1 implicitly starts a message loop, like a MessageBox in the
136   //   unit test. This can also be StartDoc or GetSaveFileName.
137   // - The thread receives a task #2 before or while in this second message
138   //   loop.
139   // - With NestableTasksAllowed set to true, the task #2 will run right away.
140   //   Otherwise, it will get executed right after task #1 completes at "thread
141   //   message loop level".
142   //
143   // DEPRECATED(https://crbug.com/750779): Use RunLoop::Type on the relevant
144   // RunLoop instead of these methods.
145   // TODO(gab): Migrate usage and delete these methods.
146   void SetNestableTasksAllowed(bool allowed);
147   bool NestableTasksAllowed() const;
148 
149   // Enables nestable tasks on the current MessageLoop while in scope.
150   // DEPRECATED(https://crbug.com/750779): This should not be used when the
151   // nested loop is driven by RunLoop (use RunLoop::Type::kNestableTasksAllowed
152   // instead). It can however still be useful in a few scenarios where re-
153   // entrancy is caused by a native message loop.
154   // TODO(gab): Remove usage of this class alongside RunLoop and rename it to
155   // ScopedApplicationTasksAllowedInNativeNestedLoop(?) for remaining use cases.
156   class BASE_EXPORT ScopedNestableTaskAllower {
157    public:
158     ScopedNestableTaskAllower();
159     ~ScopedNestableTaskAllower();
160 
161    private:
162     MessageLoop* const loop_;
163     const bool old_state_;
164   };
165 
166   // Returns true if the message loop is idle (ignoring delayed tasks). This is
167   // the same condition which triggers DoWork() to return false: i.e.
168   // out of tasks which can be processed at the current run-level -- there might
169   // be deferred non-nestable tasks remaining if currently in a nested run
170   // level.
171   bool IsIdleForTesting();
172 
173   // Binds |current| to the current thread. It will from then on be the
174   // MessageLoop driven by MessageLoopCurrent on this thread. This is only meant
175   // to be invoked by the MessageLoop itself.
176   static void BindToCurrentThreadInternal(MessageLoop* current);
177 
178   // Unbinds |current| from the current thread. Must be invoked on the same
179   // thread that invoked |BindToCurrentThreadInternal(current)|. This is only
180   // meant to be invoked by the MessageLoop itself.
181   static void UnbindFromCurrentThreadInternal(MessageLoop* current);
182 
183   // Returns true if |message_loop| is bound to MessageLoopCurrent on the
184   // current thread. This is only meant to be invoked by the MessageLoop itself.
185   static bool IsBoundToCurrentThreadInternal(MessageLoop* message_loop);
186 
187  protected:
MessageLoopCurrent(MessageLoop * current)188   explicit MessageLoopCurrent(MessageLoop* current) : current_(current) {}
189 
190   MessageLoop* const current_;
191 };
192 
193 #if !defined(OS_NACL) && !defined(OS_ANDROID)
194 
195 // ForUI extension of MessageLoopCurrent.
196 class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent {
197  public:
198   // Returns an interface for the MessageLoopForUI of the current thread.
199   // Asserts that IsSet().
200   static MessageLoopCurrentForUI Get();
201 
202   // Returns true if the current thread is running a MessageLoopForUI.
203   static bool IsSet();
204 
205   MessageLoopCurrentForUI* operator->() { return this; }
206 
207 #if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN)
208   // Please see MessagePumpLibevent for definition.
209   static_assert(std::is_same<MessagePumpForUI, MessagePumpLibevent>::value,
210                 "MessageLoopCurrentForUI::WatchFileDescriptor is not supported "
211                 "when MessagePumpForUI is not a MessagePumpLibevent.");
212   bool WatchFileDescriptor(int fd,
213                            bool persistent,
214                            MessagePumpForUI::Mode mode,
215                            MessagePumpForUI::FdWatchController* controller,
216                            MessagePumpForUI::FdWatcher* delegate);
217 #endif
218 
219 #if defined(OS_IOS)
220   // Forwards to MessageLoopForUI::Attach().
221   // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to
222   // callers and remove ability to access this method from
223   // MessageLoopCurrentForUI.
224   void Attach();
225 #endif
226 
227 #if defined(OS_ANDROID)
228   // Forwards to MessageLoopForUI::Abort().
229   // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to
230   // callers and remove ability to access this method from
231   // MessageLoopCurrentForUI.
232   void Abort();
233 #endif
234 
235  private:
MessageLoopCurrentForUI(MessageLoop * current,MessagePumpForUI * pump)236   MessageLoopCurrentForUI(MessageLoop* current, MessagePumpForUI* pump)
237       : MessageLoopCurrent(current), pump_(pump) {
238     DCHECK(pump_);
239   }
240 
241   MessagePumpForUI* const pump_;
242 };
243 
244 #endif  // !defined(OS_NACL) && !defined(OS_ANDROID)
245 
246 // ForIO extension of MessageLoopCurrent.
247 class BASE_EXPORT MessageLoopCurrentForIO : public MessageLoopCurrent {
248  public:
249   // Returns an interface for the MessageLoopForIO of the current thread.
250   // Asserts that IsSet().
251   static MessageLoopCurrentForIO Get();
252 
253   // Returns true if the current thread is running a MessageLoopForIO.
254   static bool IsSet();
255 
256   MessageLoopCurrentForIO* operator->() { return this; }
257 
258 #if !defined(OS_NACL_SFI)
259 
260 #if defined(OS_WIN)
261   // Please see MessagePumpWin for definitions of these methods.
262   HRESULT RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler);
263   bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler);
264   bool WaitForIOCompletion(DWORD timeout, MessagePumpForIO::IOHandler* filter);
265 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
266   // Please see WatchableIOMessagePumpPosix for definition.
267   // Prefer base::FileDescriptorWatcher for non-critical IO.
268   bool WatchFileDescriptor(int fd,
269                            bool persistent,
270                            MessagePumpForIO::Mode mode,
271                            MessagePumpForIO::FdWatchController* controller,
272                            MessagePumpForIO::FdWatcher* delegate);
273 #endif  // defined(OS_WIN)
274 
275 #if defined(OS_FUCHSIA)
276   // Additional watch API for native platform resources.
277   bool WatchZxHandle(zx_handle_t handle,
278                      bool persistent,
279                      zx_signals_t signals,
280                      MessagePumpForIO::ZxHandleWatchController* controller,
281                      MessagePumpForIO::ZxHandleWatcher* delegate);
282 #endif  // defined(OS_FUCHSIA)
283 
284 #endif  // !defined(OS_NACL_SFI)
285 
286  private:
MessageLoopCurrentForIO(MessageLoop * current,MessagePumpForIO * pump)287   MessageLoopCurrentForIO(MessageLoop* current, MessagePumpForIO* pump)
288       : MessageLoopCurrent(current), pump_(pump) {
289     DCHECK(pump_);
290   }
291 
292   MessagePumpForIO* const pump_;
293 };
294 
295 }  // namespace base
296 
297 #endif  // BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
298