|  | // 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/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_ |