| // Copyright 2018 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ | 
 | #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/logging.h" | 
 | #include "base/memory/scoped_refptr.h" | 
 | #include "base/message_loop/message_pump_for_io.h" | 
 | #include "base/message_loop/message_pump_for_ui.h" | 
 | #include "base/pending_task.h" | 
 | #include "base/single_thread_task_runner.h" | 
 | #include "build_config.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | class MessageLoop; | 
 |  | 
 | // MessageLoopCurrent is a proxy to the public interface of the MessageLoop | 
 | // bound to the thread it's obtained on. | 
 | // | 
 | // MessageLoopCurrent(ForUI|ForIO) is available statically through | 
 | // MessageLoopCurrent(ForUI|ForIO)::Get() on threads that have a matching | 
 | // MessageLoop instance. APIs intended for all consumers on the thread should be | 
 | // on MessageLoopCurrent(ForUI|ForIO), while APIs intended for the owner of the | 
 | // instance should be on MessageLoop(ForUI|ForIO). | 
 | // | 
 | // Why: Historically MessageLoop::current() gave access to the full MessageLoop | 
 | // API, preventing both addition of powerful owner-only APIs as well as making | 
 | // it harder to remove callers of deprecated APIs (that need to stick around for | 
 | // a few owner-only use cases and re-accrue callers after cleanup per remaining | 
 | // publicly available). | 
 | // | 
 | // As such, many methods below are flagged as deprecated and should be removed | 
 | // (or moved back to MessageLoop) once all static callers have been migrated. | 
 | class BASE_EXPORT MessageLoopCurrent { | 
 |  public: | 
 |   // MessageLoopCurrent is effectively just a disguised pointer and is fine to | 
 |   // copy around. | 
 |   MessageLoopCurrent(const MessageLoopCurrent& other) = default; | 
 |   MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = default; | 
 |  | 
 |   // Returns a proxy object to interact with the MessageLoop running the | 
 |   // current thread. It must only be used on the thread it was obtained. | 
 |   static MessageLoopCurrent Get(); | 
 |  | 
 |   // Returns true if the current thread is running a MessageLoop. Prefer this to | 
 |   // verifying the boolean value of Get() (so that Get() can ultimately DCHECK | 
 |   // it's only invoked when IsSet()). | 
 |   static bool IsSet(); | 
 |  | 
 |   // Allow MessageLoopCurrent to be used like a pointer to support the many | 
 |   // callsites that used MessageLoop::current() that way when it was a | 
 |   // MessageLoop*. | 
 |   MessageLoopCurrent* operator->() { return this; } | 
 |   explicit operator bool() const { return !!current_; } | 
 |  | 
 |   // TODO(gab): Migrate the types of variables that store MessageLoop::current() | 
 |   // and remove this implicit cast back to MessageLoop*. | 
 |   operator MessageLoop*() const { return current_; } | 
 |  | 
 |   // A DestructionObserver is notified when the current MessageLoop is being | 
 |   // destroyed.  These observers are notified prior to MessageLoop::current() | 
 |   // being changed to return NULL.  This gives interested parties the chance to | 
 |   // do final cleanup that depends on the MessageLoop. | 
 |   // | 
 |   // NOTE: Any tasks posted to the MessageLoop during this notification will | 
 |   // not be run.  Instead, they will be deleted. | 
 |   // | 
 |   // Deprecation note: Prefer SequenceLocalStorageSlot<std::unique_ptr<Foo>> to | 
 |   // DestructionObserver to bind an object's lifetime to the current | 
 |   // thread/sequence. | 
 |   class BASE_EXPORT DestructionObserver { | 
 |    public: | 
 |     virtual void WillDestroyCurrentMessageLoop() = 0; | 
 |  | 
 |    protected: | 
 |     virtual ~DestructionObserver() = default; | 
 |   }; | 
 |  | 
 |   // Add a DestructionObserver, which will start receiving notifications | 
 |   // immediately. | 
 |   void AddDestructionObserver(DestructionObserver* destruction_observer); | 
 |  | 
 |   // Remove a DestructionObserver.  It is safe to call this method while a | 
 |   // DestructionObserver is receiving a notification callback. | 
 |   void RemoveDestructionObserver(DestructionObserver* destruction_observer); | 
 |  | 
 |   // Forwards to MessageLoop::task_runner(). | 
 |   // DEPRECATED(https://crbug.com/616447): Use ThreadTaskRunnerHandle::Get() | 
 |   // instead of MessageLoopCurrent::Get()->task_runner(). | 
 |   const scoped_refptr<SingleThreadTaskRunner>& task_runner() const; | 
 |  | 
 |   // Forwards to MessageLoop::SetTaskRunner(). | 
 |   // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop | 
 |   // instance should replace its TaskRunner. | 
 |   void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner); | 
 |  | 
 |   // A TaskObserver is an object that receives task notifications from the | 
 |   // MessageLoop. | 
 |   // | 
 |   // NOTE: A TaskObserver implementation should be extremely fast! | 
 |   class BASE_EXPORT TaskObserver { | 
 |    public: | 
 |     // This method is called before processing a task. | 
 |     virtual void WillProcessTask(const PendingTask& pending_task) = 0; | 
 |  | 
 |     // This method is called after processing a task. | 
 |     virtual void DidProcessTask(const PendingTask& pending_task) = 0; | 
 |  | 
 |    protected: | 
 |     virtual ~TaskObserver() = default; | 
 |   }; | 
 |  | 
 |   // Forwards to MessageLoop::(Add|Remove)TaskObserver. | 
 |   // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop | 
 |   // instance should add task observers on it. | 
 |   void AddTaskObserver(TaskObserver* task_observer); | 
 |   void RemoveTaskObserver(TaskObserver* task_observer); | 
 |  | 
 |   // Enables or disables the recursive task processing. This happens in the case | 
 |   // of recursive message loops. Some unwanted message loops may occur when | 
 |   // using common controls or printer functions. By default, recursive task | 
 |   // processing is disabled. | 
 |   // | 
 |   // Please use |ScopedNestableTaskAllower| instead of calling these methods | 
 |   // directly.  In general, nestable message loops are to be avoided.  They are | 
 |   // dangerous and difficult to get right, so please use with extreme caution. | 
 |   // | 
 |   // The specific case where tasks get queued is: | 
 |   // - The thread is running a message loop. | 
 |   // - It receives a task #1 and executes it. | 
 |   // - The task #1 implicitly starts a message loop, like a MessageBox in the | 
 |   //   unit test. This can also be StartDoc or GetSaveFileName. | 
 |   // - The thread receives a task #2 before or while in this second message | 
 |   //   loop. | 
 |   // - With NestableTasksAllowed set to true, the task #2 will run right away. | 
 |   //   Otherwise, it will get executed right after task #1 completes at "thread | 
 |   //   message loop level". | 
 |   // | 
 |   // DEPRECATED(https://crbug.com/750779): Use RunLoop::Type on the relevant | 
 |   // RunLoop instead of these methods. | 
 |   // TODO(gab): Migrate usage and delete these methods. | 
 |   void SetNestableTasksAllowed(bool allowed); | 
 |   bool NestableTasksAllowed() const; | 
 |  | 
 |   // Enables nestable tasks on the current MessageLoop while in scope. | 
 |   // DEPRECATED(https://crbug.com/750779): This should not be used when the | 
 |   // nested loop is driven by RunLoop (use RunLoop::Type::kNestableTasksAllowed | 
 |   // instead). It can however still be useful in a few scenarios where re- | 
 |   // entrancy is caused by a native message loop. | 
 |   // TODO(gab): Remove usage of this class alongside RunLoop and rename it to | 
 |   // ScopedApplicationTasksAllowedInNativeNestedLoop(?) for remaining use cases. | 
 |   class BASE_EXPORT ScopedNestableTaskAllower { | 
 |    public: | 
 |     ScopedNestableTaskAllower(); | 
 |     ~ScopedNestableTaskAllower(); | 
 |  | 
 |    private: | 
 |     MessageLoop* const loop_; | 
 |     const bool old_state_; | 
 |   }; | 
 |  | 
 |   // Returns true if the message loop is idle (ignoring delayed tasks). This is | 
 |   // the same condition which triggers DoWork() to return false: i.e. | 
 |   // out of tasks which can be processed at the current run-level -- there might | 
 |   // be deferred non-nestable tasks remaining if currently in a nested run | 
 |   // level. | 
 |   bool IsIdleForTesting(); | 
 |  | 
 |   // Binds |current| to the current thread. It will from then on be the | 
 |   // MessageLoop driven by MessageLoopCurrent on this thread. This is only meant | 
 |   // to be invoked by the MessageLoop itself. | 
 |   static void BindToCurrentThreadInternal(MessageLoop* current); | 
 |  | 
 |   // Unbinds |current| from the current thread. Must be invoked on the same | 
 |   // thread that invoked |BindToCurrentThreadInternal(current)|. This is only | 
 |   // meant to be invoked by the MessageLoop itself. | 
 |   static void UnbindFromCurrentThreadInternal(MessageLoop* current); | 
 |  | 
 |   // Returns true if |message_loop| is bound to MessageLoopCurrent on the | 
 |   // current thread. This is only meant to be invoked by the MessageLoop itself. | 
 |   static bool IsBoundToCurrentThreadInternal(MessageLoop* message_loop); | 
 |  | 
 |  protected: | 
 |   explicit MessageLoopCurrent(MessageLoop* current) : current_(current) {} | 
 |  | 
 |   MessageLoop* const current_; | 
 | }; | 
 |  | 
 | #if !defined(OS_NACL) | 
 |  | 
 | // ForUI extension of MessageLoopCurrent. | 
 | class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent { | 
 |  public: | 
 |   // Returns an interface for the MessageLoopForUI of the current thread. | 
 |   // Asserts that IsSet(). | 
 |   static MessageLoopCurrentForUI Get(); | 
 |  | 
 |   // Returns true if the current thread is running a MessageLoopForUI. | 
 |   static bool IsSet(); | 
 |  | 
 |   MessageLoopCurrentForUI* operator->() { return this; } | 
 |  | 
 | #if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN) | 
 |   // Please see MessagePumpLibevent for definition. | 
 |   static_assert(std::is_same<MessagePumpForUI, MessagePumpLibevent>::value, | 
 |                 "MessageLoopCurrentForUI::WatchFileDescriptor is not supported " | 
 |                 "when MessagePumpForUI is not a MessagePumpLibevent."); | 
 |   bool WatchFileDescriptor(int fd, | 
 |                            bool persistent, | 
 |                            MessagePumpForUI::Mode mode, | 
 |                            MessagePumpForUI::FdWatchController* controller, | 
 |                            MessagePumpForUI::FdWatcher* delegate); | 
 | #endif | 
 |  | 
 | #if defined(OS_IOS) | 
 |   // Forwards to MessageLoopForUI::Attach(). | 
 |   // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to | 
 |   // callers and remove ability to access this method from | 
 |   // MessageLoopCurrentForUI. | 
 |   void Attach(); | 
 | #endif | 
 |  | 
 | #if defined(OS_ANDROID) | 
 |   // Forwards to MessageLoopForUI::Start(). | 
 |   // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to | 
 |   // callers and remove ability to access this method from | 
 |   // MessageLoopCurrentForUI. | 
 |   void Start(); | 
 |  | 
 |   // Forwards to MessageLoopForUI::Abort(). | 
 |   // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to | 
 |   // callers and remove ability to access this method from | 
 |   // MessageLoopCurrentForUI. | 
 |   void Abort(); | 
 | #endif | 
 |  | 
 |  private: | 
 |   MessageLoopCurrentForUI(MessageLoop* current, MessagePumpForUI* pump) | 
 |       : MessageLoopCurrent(current), pump_(pump) { | 
 |     DCHECK(pump_); | 
 |   } | 
 |  | 
 |   MessagePumpForUI* const pump_; | 
 | }; | 
 |  | 
 | #endif  // !defined(OS_NACL) | 
 |  | 
 | // ForIO extension of MessageLoopCurrent. | 
 | class BASE_EXPORT MessageLoopCurrentForIO : public MessageLoopCurrent { | 
 |  public: | 
 |   // Returns an interface for the MessageLoopForIO of the current thread. | 
 |   // Asserts that IsSet(). | 
 |   static MessageLoopCurrentForIO Get(); | 
 |  | 
 |   // Returns true if the current thread is running a MessageLoopForIO. | 
 |   static bool IsSet(); | 
 |  | 
 |   MessageLoopCurrentForIO* operator->() { return this; } | 
 |  | 
 | #if !defined(OS_NACL_SFI) | 
 |  | 
 | #if defined(OS_WIN) | 
 |   // Please see MessagePumpWin for definitions of these methods. | 
 |   void RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler); | 
 |   bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler); | 
 |   bool WaitForIOCompletion(DWORD timeout, MessagePumpForIO::IOHandler* filter); | 
 | #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | 
 |   // Please see WatchableIOMessagePumpPosix for definition. | 
 |   // Prefer base::FileDescriptorWatcher for non-critical IO. | 
 |   bool WatchFileDescriptor(int fd, | 
 |                            bool persistent, | 
 |                            MessagePumpForIO::Mode mode, | 
 |                            MessagePumpForIO::FdWatchController* controller, | 
 |                            MessagePumpForIO::FdWatcher* delegate); | 
 | #endif  // defined(OS_WIN) | 
 |  | 
 | #if defined(OS_FUCHSIA) | 
 |   // Additional watch API for native platform resources. | 
 |   bool WatchZxHandle(zx_handle_t handle, | 
 |                      bool persistent, | 
 |                      zx_signals_t signals, | 
 |                      MessagePumpForIO::ZxHandleWatchController* controller, | 
 |                      MessagePumpForIO::ZxHandleWatcher* delegate); | 
 | #endif  // defined(OS_FUCHSIA) | 
 |  | 
 | #endif  // !defined(OS_NACL_SFI) | 
 |  | 
 |  private: | 
 |   MessageLoopCurrentForIO(MessageLoop* current, MessagePumpForIO* pump) | 
 |       : MessageLoopCurrent(current), pump_(pump) { | 
 |     DCHECK(pump_); | 
 |   } | 
 |  | 
 |   MessagePumpForIO* const pump_; | 
 | }; | 
 |  | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ |