Revert "Remove MessageLoopBase"

This reverts commit 58017e6cc6dd25207cae01ebe2d7961d12a46b3f.

Reason for revert: win-asan test failure

https://crbug.com/953465

Original change's description:
> Remove MessageLoopBase
> 
> Bug: 891670
> Change-Id: Iff6a2b4685f455509553779c7c04afd3c6f6c4e6
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1538289
> Commit-Queue: Carlos Caballero <carlscab@google.com>
> Reviewed-by: Gabriel Charette <gab@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#651343}

TBR=gab@chromium.org,carlscab@google.com

Change-Id: I213af8c40d0b5db91abb6f84c9de531be3e18f98
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 891670
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1570660
Reviewed-by: Aleks Totic <atotic@chromium.org>
Commit-Queue: Aleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#651461}
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index afcf04d..ae58f82 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -56,10 +56,20 @@
 
 MessageLoop::~MessageLoop() {
   // Clean up any unprocessed tasks, but take care: deleting a task could
-  // result in the addition of more tasks (e.g., via DeleteSoon). This is taken
-  // care by the queue as it will prevent further tasks from being posted to its
-  // associated TaskRunner instances.
-  default_task_queue_->ShutdownTaskQueue();
+  // result in the addition of more tasks (e.g., via DeleteSoon).  We set a
+  // limit on the number of times we will allow a deleted task to generate more
+  // tasks.  Normally, we should only pass through this loop once or twice.  If
+  // we end up hitting the loop limit, then it is probably due to one task that
+  // is being stubborn.  Inspect the queues to see who is left.
+  bool tasks_remain;
+  for (int i = 0; i < 100; ++i) {
+    backend_->DeletePendingTasks();
+    // If we end up with empty queues, then break out of the loop.
+    tasks_remain = backend_->HasTasks();
+    if (!tasks_remain)
+      break;
+  }
+  DCHECK(!tasks_remain);
 
   // If |pump_| is non-null, this message loop has been bound and should be the
   // current one on this thread. Otherwise, this loop is being destructed before
@@ -131,20 +141,24 @@
 // implementation detail. http://crbug.com/703346
 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
-  sequence_manager_->AddTaskObserver(task_observer);
+  backend_->AddTaskObserver(task_observer);
 }
 
 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
-  sequence_manager_->RemoveTaskObserver(task_observer);
+  backend_->RemoveTaskObserver(task_observer);
 }
 
 bool MessageLoop::IsBoundToCurrentThread() const {
-  return sequence_manager_->IsBoundToCurrentThread();
+  return backend_->IsBoundToCurrentThread();
 }
 
 bool MessageLoop::IsIdleForTesting() {
-  return sequence_manager_->IsIdleForTesting();
+  return backend_->IsIdleForTesting();
+}
+
+MessageLoopBase* MessageLoop::GetMessageLoopBase() {
+  return backend_.get();
 }
 
 //------------------------------------------------------------------------------
@@ -161,9 +175,8 @@
 }
 
 MessageLoop::MessageLoop(Type type, std::unique_ptr<MessagePump> custom_pump)
-    : sequence_manager_(
-          sequence_manager::internal::SequenceManagerImpl::CreateUnbound(
-              sequence_manager::SequenceManager::Settings{type})),
+    : backend_(sequence_manager::internal::SequenceManagerImpl::CreateUnbound(
+          sequence_manager::SequenceManager::Settings{type})),
       default_task_queue_(CreateDefaultTaskQueue()),
       type_(type),
       custom_pump_(std::move(custom_pump)) {
@@ -173,9 +186,13 @@
 
 scoped_refptr<sequence_manager::TaskQueue>
 MessageLoop::CreateDefaultTaskQueue() {
-  auto default_task_queue = sequence_manager_->CreateTaskQueue(
-      sequence_manager::TaskQueue::Spec("default_tq"));
-  sequence_manager_->SetTaskRunner(default_task_queue->task_runner());
+  sequence_manager::internal::SequenceManagerImpl* manager =
+      static_cast<sequence_manager::internal::SequenceManagerImpl*>(
+          backend_.get());
+  scoped_refptr<sequence_manager::TaskQueue> default_task_queue =
+      manager->CreateTaskQueueWithType<sequence_manager::TaskQueue>(
+          sequence_manager::TaskQueue::Spec("default_tq"));
+  manager->SetTaskRunner(default_task_queue->task_runner());
   return default_task_queue;
 }
 
@@ -191,7 +208,7 @@
   DCHECK(!MessageLoopCurrent::IsSet())
       << "should only have one message loop per thread";
 
-  sequence_manager_->BindToCurrentThread(std::move(pump));
+  backend_->BindToCurrentThread(std::move(pump));
 }
 
 std::unique_ptr<MessagePump> MessageLoop::CreateMessagePump() {
@@ -203,21 +220,21 @@
 }
 
 void MessageLoop::SetTimerSlack(TimerSlack timer_slack) {
-  sequence_manager_->SetTimerSlack(timer_slack);
+  backend_->SetTimerSlack(timer_slack);
 }
 
 std::string MessageLoop::GetThreadName() const {
-  return sequence_manager_->GetThreadName();
+  return backend_->GetThreadName();
 }
 
 scoped_refptr<SingleThreadTaskRunner> MessageLoop::task_runner() const {
-  return sequence_manager_->GetTaskRunner();
+  return backend_->GetTaskRunner();
 }
 
 void MessageLoop::SetTaskRunner(
     scoped_refptr<SingleThreadTaskRunner> task_runner) {
   DCHECK(task_runner);
-  sequence_manager_->SetTaskRunner(task_runner);
+  backend_->SetTaskRunner(task_runner);
 }
 
 #if !defined(OS_NACL)
@@ -235,7 +252,7 @@
 
 #if defined(OS_IOS)
 void MessageLoopForUI::Attach() {
-  sequence_manager_->AttachToMessagePump();
+  backend_->AttachToMessagePump();
 }
 #endif  // defined(OS_IOS)
 
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index ddfed50..46782b4 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -34,7 +34,8 @@
 class TaskQueue;
 namespace internal {
 class SequenceManagerImpl;
-}  // namespace internal
+class ThreadControllerImpl;
+}
 }  // namespace sequence_manager
 
 // A MessageLoop is used to process events for a particular thread.  There is
@@ -80,8 +81,11 @@
 // Please be SURE your task is reentrant (nestable) and all global variables
 // are stable and accessible before calling SetNestableTasksAllowed(true).
 
-class BASE_EXPORT MessageLoop {
+class BASE_EXPORT MessageLoopBase {
  public:
+  MessageLoopBase() = default;
+  virtual ~MessageLoopBase() = default;
+
   // A MessageLoop has a particular type, which indicates the set of
   // asynchronous events it may process in addition to tasks and timers.
   //
@@ -105,7 +109,7 @@
   // TYPE_CUSTOM
   //   MessagePump was supplied to constructor.
   //
-  enum class Type {
+  enum Type {
     TYPE_DEFAULT,
     TYPE_UI,
     TYPE_CUSTOM,
@@ -115,6 +119,106 @@
 #endif  // defined(OS_ANDROID)
   };
 
+  // Returns true if this loop is |type|. This allows subclasses (especially
+  // those in tests) to specialize how they are identified.
+  virtual bool IsType(Type type) const = 0;
+
+  // Returns the name of the thread this message loop is bound to. This function
+  // is only valid when this message loop is running, BindToCurrentThread has
+  // already been called and has an "happens-before" relationship with this call
+  // (this relationship is obtained implicitly by the MessageLoop's task posting
+  // system unless calling this very early).
+  virtual std::string GetThreadName() const = 0;
+
+  using DestructionObserver = MessageLoopCurrent::DestructionObserver;
+
+  // Add a DestructionObserver, which will start receiving notifications
+  // immediately.
+  virtual void AddDestructionObserver(
+      DestructionObserver* destruction_observer) = 0;
+
+  // Remove a DestructionObserver.  It is safe to call this method while a
+  // DestructionObserver is receiving a notification callback.
+  virtual void RemoveDestructionObserver(
+      DestructionObserver* destruction_observer) = 0;
+
+  // TODO(altimin,yutak): Replace with base::TaskObserver.
+  using TaskObserver = MessageLoopCurrent::TaskObserver;
+
+  // These functions can only be called on the same thread that |this| is
+  // running on.
+  // These functions must not be called from a TaskObserver callback.
+  virtual void AddTaskObserver(TaskObserver* task_observer) = 0;
+  virtual void RemoveTaskObserver(TaskObserver* task_observer) = 0;
+
+  // When this functionality is enabled, the queue time will be recorded for
+  // posted tasks.
+  virtual void SetAddQueueTimeToTasks(bool enable) = 0;
+
+  // Returns true if this is the active MessageLoop for the current thread.
+  virtual bool IsBoundToCurrentThread() const = 0;
+
+  // 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.
+  virtual bool IsIdleForTesting() = 0;
+
+  // Returns the MessagePump owned by this MessageLoop if any.
+  virtual MessagePump* GetMessagePump() const = 0;
+
+  // Sets a new TaskRunner for this message loop. If the message loop was
+  // already bound, this must be called on the thread to which it is bound.
+  // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
+  virtual void SetTaskRunner(
+      scoped_refptr<SingleThreadTaskRunner> task_runner) = 0;
+
+  // Gets the TaskRunner associated with this message loop.
+  // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
+  virtual scoped_refptr<SingleThreadTaskRunner> GetTaskRunner() = 0;
+
+  // Binds the MessageLoop to the current thread using |pump|.
+  virtual void BindToCurrentThread(std::unique_ptr<MessagePump> pump) = 0;
+
+  // Returns true if the MessageLoop retains any tasks inside it.
+  virtual bool HasTasks() = 0;
+
+  // Deletes all tasks associated with this MessageLoop. Note that the tasks
+  // can post other tasks when destructed.
+  virtual void DeletePendingTasks() = 0;
+
+ protected:
+  friend class MessageLoop;
+  friend class MessageLoopForUI;
+  friend class MessageLoopCurrent;
+  friend class MessageLoopCurrentForIO;
+  friend class MessageLoopCurrentForUI;
+  friend class Thread;
+  friend class sequence_manager::internal::ThreadControllerImpl;
+
+  // Explicitly allow or disallow task execution. Task execution is disallowed
+  // implicitly when we enter a nested runloop.
+  virtual void SetTaskExecutionAllowed(bool allowed) = 0;
+
+  // Whether task execution is allowed at the moment.
+  virtual bool IsTaskExecutionAllowed() const = 0;
+
+#if defined(OS_IOS)
+  virtual void AttachToMessagePump() = 0;
+#endif
+
+  virtual Type GetType() const = 0;
+
+  // Set the timer slack for this message loop.
+  // TODO(alexclarke): Remove this as part of https://crbug.com/891670.
+  virtual void SetTimerSlack(TimerSlack timer_slack) = 0;
+};
+
+class BASE_EXPORT MessageLoop {
+ public:
+  // For migration convenience we define the Type enum.
+  using Type = MessageLoopBase::Type;
   static constexpr Type TYPE_DEFAULT = Type::TYPE_DEFAULT;
   static constexpr Type TYPE_UI = Type::TYPE_UI;
   static constexpr Type TYPE_CUSTOM = Type::TYPE_CUSTOM;
@@ -125,7 +229,7 @@
 
   // Normally, it is not necessary to instantiate a MessageLoop.  Instead, it
   // is typical to make use of the current thread's MessageLoop instance.
-  explicit MessageLoop(Type type = Type::TYPE_DEFAULT);
+  explicit MessageLoop(Type type = TYPE_DEFAULT);
   // Creates a TYPE_CUSTOM MessageLoop with the supplied MessagePump, which must
   // be non-NULL.
   explicit MessageLoop(std::unique_ptr<MessagePump> custom_pump);
@@ -186,6 +290,8 @@
   // TODO(alexclarke): Make this const when MessageLoopImpl goes away.
   bool IsIdleForTesting();
 
+  MessageLoopBase* GetMessageLoopBase();
+
   //----------------------------------------------------------------------------
  protected:
   using MessagePumpFactoryCallback =
@@ -202,16 +308,17 @@
   // Configure various members and bind this message loop to the current thread.
   void BindToCurrentThread();
 
-  // A raw pointer to the MessagePump handed-off to |sequence_manager_|.
-  // Valid for the lifetime of |sequence_manager_|.
+  // A raw pointer to the MessagePump handed-off to |backend_|.
+  // Valid for the lifetime of |backend_|.
   MessagePump* pump_ = nullptr;
 
-  // TODO(crbug.com/891670): We shouldn't publicly expose all of
-  // SequenceManagerImpl.
-  const std::unique_ptr<sequence_manager::internal::SequenceManagerImpl>
-      sequence_manager_;
-  // SequenceManager requires an explicit initialisation of the default task
-  // queue.
+  // The SequenceManager-based implementation of the MessageLoop.
+  // TODO(crbug.com/891670): MessageLoopBase is now always a
+  // SequenceManagerImpl, this can be simplified but we also shouldn't publicly
+  // expose all of SequenceManagerImpl either.
+  const std::unique_ptr<MessageLoopBase> backend_;
+  // SequenceManager-based backend requires an explicit initialisation of the
+  // default task queue.
   const scoped_refptr<sequence_manager::TaskQueue> default_task_queue_;
 
  private:
@@ -238,11 +345,6 @@
 
   std::unique_ptr<MessagePump> CreateMessagePump();
 
-  sequence_manager::internal::SequenceManagerImpl* GetSequenceManagerImpl()
-      const {
-    return sequence_manager_.get();
-  }
-
   const Type type_;
 
   // If set this will be returned by the next call to CreateMessagePump().
diff --git a/base/message_loop/message_loop_current.cc b/base/message_loop/message_loop_current.cc
index 2e2adfa..7dcab95 100644
--- a/base/message_loop/message_loop_current.cc
+++ b/base/message_loop/message_loop_current.cc
@@ -19,14 +19,13 @@
 // MessageLoopCurrent
 
 // static
-sequence_manager::internal::SequenceManagerImpl*
-MessageLoopCurrent::GetCurrentSequenceManagerImpl() {
+MessageLoopBase* MessageLoopCurrent::GetCurrentMessageLoopBase() {
   return sequence_manager::internal::SequenceManagerImpl::GetCurrent();
 }
 
 // static
 MessageLoopCurrent MessageLoopCurrent::Get() {
-  return MessageLoopCurrent(GetCurrentSequenceManagerImpl());
+  return MessageLoopCurrent(GetCurrentMessageLoopBase());
 }
 
 // static
@@ -36,7 +35,7 @@
 
 // static
 bool MessageLoopCurrent::IsSet() {
-  return !!GetCurrentSequenceManagerImpl();
+  return !!GetCurrentMessageLoopBase();
 }
 
 void MessageLoopCurrent::AddDestructionObserver(
@@ -67,7 +66,7 @@
 }
 
 bool MessageLoopCurrent::IsBoundToCurrentThread() const {
-  return current_ == GetCurrentSequenceManagerImpl();
+  return current_ == GetCurrentMessageLoopBase();
 }
 
 bool MessageLoopCurrent::IsIdleForTesting() {
@@ -100,13 +99,13 @@
 }
 
 MessageLoopCurrent::ScopedNestableTaskAllower::ScopedNestableTaskAllower()
-    : sequence_manager_(GetCurrentSequenceManagerImpl()),
-      old_state_(sequence_manager_->IsTaskExecutionAllowed()) {
-  sequence_manager_->SetTaskExecutionAllowed(true);
+    : loop_(GetCurrentMessageLoopBase()),
+      old_state_(loop_->IsTaskExecutionAllowed()) {
+  loop_->SetTaskExecutionAllowed(true);
 }
 
 MessageLoopCurrent::ScopedNestableTaskAllower::~ScopedNestableTaskAllower() {
-  sequence_manager_->SetTaskExecutionAllowed(old_state_);
+  loop_->SetTaskExecutionAllowed(old_state_);
 }
 
 bool MessageLoopCurrent::operator==(const MessageLoopCurrent& other) const {
@@ -120,27 +119,26 @@
 
 // static
 MessageLoopCurrentForUI MessageLoopCurrentForUI::Get() {
-  auto* sequence_manager = GetCurrentSequenceManagerImpl();
-  DCHECK(sequence_manager);
+  MessageLoopBase* loop = GetCurrentMessageLoopBase();
+  DCHECK(loop);
 #if defined(OS_ANDROID)
-  DCHECK(sequence_manager->IsType(MessageLoop::TYPE_UI) ||
-         sequence_manager->IsType(MessageLoop::TYPE_JAVA));
+  DCHECK(loop->IsType(MessageLoop::TYPE_UI) ||
+         loop->IsType(MessageLoop::TYPE_JAVA));
 #else   // defined(OS_ANDROID)
-  DCHECK(sequence_manager->IsType(MessageLoop::TYPE_UI));
+  DCHECK(loop->IsType(MessageLoop::TYPE_UI));
 #endif  // defined(OS_ANDROID)
-  return MessageLoopCurrentForUI(sequence_manager);
+  return MessageLoopCurrentForUI(loop);
 }
 
 // static
 bool MessageLoopCurrentForUI::IsSet() {
-  sequence_manager::internal::SequenceManagerImpl* sequence_manager =
-      GetCurrentSequenceManagerImpl();
-  return sequence_manager &&
+  MessageLoopBase* loop = GetCurrentMessageLoopBase();
+  return loop &&
 #if defined(OS_ANDROID)
-         (sequence_manager->IsType(MessageLoop::TYPE_UI) ||
-          sequence_manager->IsType(MessageLoop::TYPE_JAVA));
+         (loop->IsType(MessageLoop::TYPE_UI) ||
+          loop->IsType(MessageLoop::TYPE_JAVA));
 #else   // defined(OS_ANDROID)
-         sequence_manager->IsType(MessageLoop::TYPE_UI);
+         loop->IsType(MessageLoop::TYPE_UI);
 #endif  // defined(OS_ANDROID)
 }
 
@@ -192,16 +190,16 @@
 
 // static
 MessageLoopCurrentForIO MessageLoopCurrentForIO::Get() {
-  auto* sequence_manager = GetCurrentSequenceManagerImpl();
-  DCHECK(sequence_manager);
-  DCHECK(sequence_manager->IsType(MessageLoop::TYPE_IO));
-  return MessageLoopCurrentForIO(sequence_manager);
+  MessageLoopBase* loop = GetCurrentMessageLoopBase();
+  DCHECK(loop);
+  DCHECK(loop->IsType(MessageLoop::TYPE_IO));
+  return MessageLoopCurrentForIO(loop);
 }
 
 // static
 bool MessageLoopCurrentForIO::IsSet() {
-  auto* sequence_manager = GetCurrentSequenceManagerImpl();
-  return sequence_manager && sequence_manager->IsType(MessageLoop::TYPE_IO);
+  MessageLoopBase* loop = GetCurrentMessageLoopBase();
+  return loop && loop->IsType(MessageLoop::TYPE_IO);
 }
 
 MessagePumpForIO* MessageLoopCurrentForIO::GetMessagePumpForIO() const {
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h
index 270c6593..1809f87 100644
--- a/base/message_loop/message_loop_current.h
+++ b/base/message_loop/message_loop_current.h
@@ -23,6 +23,7 @@
 
 namespace base {
 
+class MessageLoopBase;
 class MessageLoopImpl;
 
 namespace sequence_manager {
@@ -171,7 +172,7 @@
     ~ScopedNestableTaskAllower();
 
    private:
-    sequence_manager::internal::SequenceManagerImpl* const sequence_manager_;
+    MessageLoopBase* const loop_;
     const bool old_state_;
   };
 
@@ -186,12 +187,9 @@
   bool IsIdleForTesting();
 
  protected:
-  explicit MessageLoopCurrent(
-      sequence_manager::internal::SequenceManagerImpl* sequence_manager)
-      : current_(sequence_manager) {}
+  explicit MessageLoopCurrent(MessageLoopBase* current) : current_(current) {}
 
-  static sequence_manager::internal::SequenceManagerImpl*
-  GetCurrentSequenceManagerImpl();
+  static MessageLoopBase* GetCurrentMessageLoopBase();
 
   friend class MessageLoopImpl;
   friend class MessagePumpLibeventTest;
@@ -201,7 +199,7 @@
   friend class MessageLoopTaskRunnerTest;
   friend class web::TestWebThreadBundle;
 
-  sequence_manager::internal::SequenceManagerImpl* current_;
+  MessageLoopBase* current_;
 };
 
 #if !defined(OS_NACL)
@@ -252,8 +250,7 @@
 #endif
 
  private:
-  explicit MessageLoopCurrentForUI(
-      sequence_manager::internal::SequenceManagerImpl* current)
+  explicit MessageLoopCurrentForUI(MessageLoopBase* current)
       : MessageLoopCurrent(current) {}
 
   MessagePumpForUI* GetMessagePumpForUI() const;
@@ -309,8 +306,7 @@
 #endif  // !defined(OS_NACL_SFI)
 
  private:
-  explicit MessageLoopCurrentForIO(
-      sequence_manager::internal::SequenceManagerImpl* current)
+  explicit MessageLoopCurrentForIO(MessageLoopBase* current)
       : MessageLoopCurrent(current) {}
 
   MessagePumpForIO* GetMessagePumpForIO() const;
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index c9605a4..fe65fb7 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -2328,11 +2328,23 @@
 }  // namespace
 
 // Test that MessageLoop destruction handles a task's destructor posting another
-// task.
-TEST(MessageLoopDestructionTest, DestroysFineWithPostTaskOnDestroy) {
+// task by:
+//  1) Not getting stuck clearing its task queue.
+//  2) DCHECKing when clearing pending tasks many times still doesn't yield an
+//     empty queue.
+TEST(MessageLoopDestructionTest, ExpectDeathWithStubbornPostTaskOnDestroy) {
   std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
 
-  PostTaskOnDestroy::PostTaskWithPostingDestructor(1000);
+  EXPECT_DCHECK_DEATH({
+    PostTaskOnDestroy::PostTaskWithPostingDestructor(1000);
+    loop.reset();
+  });
+}
+
+TEST(MessageLoopDestructionTest, DestroysFineWithReasonablePostTaskOnDestroy) {
+  std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
+
+  PostTaskOnDestroy::PostTaskWithPostingDestructor(10);
   loop.reset();
 }
 
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc
index c3e85f6..b7cfb6e 100644
--- a/base/message_loop/message_pump_perftest.cc
+++ b/base/message_loop/message_pump_perftest.cc
@@ -10,13 +10,11 @@
 #include "base/format_macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -177,12 +175,12 @@
     }
   }
 
-  sequence_manager::internal::SequenceManagerImpl* target_message_loop_base() {
+  MessageLoopBase* target_message_loop_base() {
 #if defined(OS_ANDROID)
     if (java_thread_)
-      return java_thread_->message_loop()->GetSequenceManagerImpl();
+      return java_thread_->message_loop()->GetMessageLoopBase();
 #endif
-    return MessageLoopCurrent::Get()->GetCurrentSequenceManagerImpl();
+    return message_loop_->GetMessageLoopBase();
   }
 
  private:
diff --git a/base/message_loop/message_pump_unittest.cc b/base/message_loop/message_pump_unittest.cc
index 220a7e0..0dc49be 100644
--- a/base/message_loop/message_pump_unittest.cc
+++ b/base/message_loop/message_pump_unittest.cc
@@ -28,9 +28,9 @@
 
 namespace {
 
-bool PumpTypeUsesDoSomeWork(MessageLoop::Type type) {
+bool PumpTypeUsesDoSomeWork(MessageLoopBase::Type type) {
   switch (type) {
-    case MessageLoop::Type::TYPE_DEFAULT:
+    case MessageLoopBase::Type::TYPE_DEFAULT:
 #if defined(OS_IOS)
       // iOS uses a MessagePumpCFRunLoop instead of MessagePumpDefault for
       // TYPE_DEFAULT. TODO(gab): migrate MessagePumpCFRunLoop too.
@@ -39,7 +39,7 @@
       return true;
 #endif
 
-    case MessageLoop::Type::TYPE_UI:
+    case MessageLoopBase::Type::TYPE_UI:
 #if defined(OS_IOS)
       // iOS uses a MessagePumpDefault for UI in unit tests, ref.
       // test_support_ios.mm::CreateMessagePumpForUIForTests().
@@ -56,7 +56,7 @@
       return false;
 #endif
 
-    case MessageLoop::Type::TYPE_IO:
+    case MessageLoopBase::Type::TYPE_IO:
 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
       return true;
 #elif defined(OS_POSIX) && !defined(OS_NACL_SFI)
@@ -69,9 +69,9 @@
       return false;
 #endif
 
-    case MessageLoop::Type::TYPE_CUSTOM:
+    case MessageLoopBase::Type::TYPE_CUSTOM:
 #if defined(OS_ANDROID)
-    case MessageLoop::Type::TYPE_JAVA:
+    case MessageLoopBase::Type::TYPE_JAVA:
 #endif  // defined(OS_ANDROID)
       // Not tested in this file.
       NOTREACHED();
@@ -96,7 +96,7 @@
   DISALLOW_COPY_AND_ASSIGN(MockMessagePumpDelegate);
 };
 
-class MessagePumpTest : public ::testing::TestWithParam<MessageLoop::Type> {
+class MessagePumpTest : public ::testing::TestWithParam<MessageLoopBase::Type> {
  public:
   MessagePumpTest()
       : message_pump_(MessageLoop::CreateMessagePumpForType(GetParam())) {}
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h
index 13ddd3e..42c2207 100644
--- a/base/task/sequence_manager/sequence_manager_impl.h
+++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -54,7 +54,6 @@
 
 class RealTimeDomain;
 class TaskQueueImpl;
-class ThreadControllerImpl;
 
 // The task queue manager provides N task queues and a selector interface for
 // choosing which task queue to service next. Each task queue consists of two
@@ -72,7 +71,8 @@
     : public SequenceManager,
       public internal::SequencedTaskSource,
       public internal::TaskQueueSelector::Observer,
-      public RunLoop::NestingObserver {
+      public RunLoop::NestingObserver,
+      public MessageLoopBase {
  public:
   using Observer = SequenceManager::Observer;
 
@@ -97,6 +97,8 @@
       scoped_refptr<SingleThreadTaskRunner> task_runner,
       SequenceManager::Settings settings);
 
+  void BindToMessageLoop(MessageLoopBase* message_loop_base);
+
   // SequenceManager implementation:
   void BindToCurrentThread() override;
   void BindToMessagePump(std::unique_ptr<MessagePump> message_pump) override;
@@ -128,31 +130,33 @@
   bool HasPendingHighResolutionTasks() override;
   bool OnSystemIdle() override;
 
-  void AddTaskObserver(MessageLoop::TaskObserver* task_observer);
-  void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer);
+  // MessageLoopBase implementation:
+  void AddTaskObserver(MessageLoop::TaskObserver* task_observer) override;
+  void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) override;
   void AddDestructionObserver(
-      MessageLoopCurrent::DestructionObserver* destruction_observer);
+      MessageLoopCurrent::DestructionObserver* destruction_observer) override;
   void RemoveDestructionObserver(
-      MessageLoopCurrent::DestructionObserver* destruction_observer);
+      MessageLoopCurrent::DestructionObserver* destruction_observer) override;
   // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
-  void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
+  void SetTaskRunner(
+      scoped_refptr<SingleThreadTaskRunner> task_runner) override;
   // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
-  scoped_refptr<SingleThreadTaskRunner> GetTaskRunner();
-  std::string GetThreadName() const;
-  bool IsBoundToCurrentThread() const;
-  MessagePump* GetMessagePump() const;
-  bool IsType(MessageLoop::Type type) const;
-  void SetAddQueueTimeToTasks(bool enable);
-  void SetTaskExecutionAllowed(bool allowed);
-  bool IsTaskExecutionAllowed() const;
+  scoped_refptr<SingleThreadTaskRunner> GetTaskRunner() override;
+  std::string GetThreadName() const override;
+  bool IsBoundToCurrentThread() const override;
+  MessagePump* GetMessagePump() const override;
+  bool IsType(MessageLoop::Type type) const override;
+  void SetAddQueueTimeToTasks(bool enable) override;
+  void SetTaskExecutionAllowed(bool allowed) override;
+  bool IsTaskExecutionAllowed() const override;
 #if defined(OS_IOS)
-  void AttachToMessagePump();
+  void AttachToMessagePump() override;
 #endif
   bool IsIdleForTesting() override;
-  void BindToCurrentThread(std::unique_ptr<MessagePump> pump);
-  void DeletePendingTasks();
-  bool HasTasks();
-  MessageLoop::Type GetType() const;
+  void BindToCurrentThread(std::unique_ptr<MessagePump> pump) override;
+  void DeletePendingTasks() override;
+  bool HasTasks() override;
+  MessageLoop::Type GetType() const override;
 
   // Requests that a task to process work is scheduled.
   void ScheduleWork();