Introduce RunLoop::OverrideDelegateForCurrentThreadForTesting().

This is a prerequisite to enable ScopedTaskEnvironment MOCK_TIME
on top of any RunLoop::Delegate (i.e. on top of MessageLoopForUI/ForIO).

This CL also removes RunLoop::Delegate::Client::IsNested() as it
was a mere shortcut for its TLS complement and had to switch to
using TLS itself to remain valid in override scenarios...
Ran base_perftests.exe --gtest_filter=*MessageLoop* in static/Release
and things look the same.

Bug: 708584
Change-Id: I143f6e6afb47de11f95702c337dbe63eb0887596
Reviewed-on: https://chromium-review.googlesource.com/784214
Commit-Queue: Gabriel Charette <gab@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521228}
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 2c8899bf..519eb8f 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -334,7 +334,7 @@
   DCHECK_EQ(this, current());
   if (application_tasks_allowed && !task_execution_allowed_) {
     // Allow nested task execution as explicitly requested.
-    DCHECK(run_loop_client_->IsNested());
+    DCHECK(RunLoop::IsNestedOnCurrentThread());
     task_execution_allowed_ = true;
     pump_->Run(this);
     task_execution_allowed_ = false;
@@ -363,7 +363,7 @@
 }
 
 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
-  if (run_loop_client_->IsNested())
+  if (RunLoop::IsNestedOnCurrentThread())
     return false;
 
   while (incoming_task_queue_->deferred_tasks().HasTasks()) {
@@ -399,7 +399,7 @@
 
 bool MessageLoop::DeferOrRunPendingTask(PendingTask pending_task) {
   if (pending_task.nestable == Nestable::kNestable ||
-      !run_loop_client_->IsNested()) {
+      !RunLoop::IsNestedOnCurrentThread()) {
     RunTask(&pending_task);
     // Show that we ran a task (Note: a new one might arrive as a
     // consequence!).
diff --git a/base/run_loop.cc b/base/run_loop.cc
index 61230c62..880625a 100644
--- a/base/run_loop.cc
+++ b/base/run_loop.cc
@@ -50,13 +50,8 @@
 bool RunLoop::Delegate::Client::ShouldQuitWhenIdle() const {
   DCHECK_CALLED_ON_VALID_THREAD(outer_->bound_thread_checker_);
   DCHECK(outer_->bound_);
-  return outer_->active_run_loops_.top()->quit_when_idle_received_;
-}
-
-bool RunLoop::Delegate::Client::IsNested() const {
-  DCHECK_CALLED_ON_VALID_THREAD(outer_->bound_thread_checker_);
-  DCHECK(outer_->bound_);
-  return outer_->active_run_loops_.size() > 1;
+  return outer_->was_overriden_ ||
+         outer_->active_run_loops_.top()->quit_when_idle_received_;
 }
 
 RunLoop::Delegate::Client::Client(Delegate* outer) : outer_(outer) {}
@@ -76,6 +71,27 @@
   return &delegate->client_interface_;
 }
 
+// static
+std::pair<RunLoop::Delegate::Client*, RunLoop::Delegate*>
+RunLoop::OverrideDelegateForCurrentThreadForTesting(Delegate* delegate) {
+  // Bind |delegate| to this thread.
+  DCHECK(!delegate->bound_);
+  DCHECK_CALLED_ON_VALID_THREAD(delegate->bound_thread_checker_);
+
+  // Overriding cannot be performed while running.
+  DCHECK(!IsRunningOnCurrentThread());
+
+  // Override the current Delegate (there must be one).
+  Delegate* overriden_delegate = tls_delegate.Get().Get();
+  DCHECK(overriden_delegate);
+  DCHECK(overriden_delegate->bound_);
+  overriden_delegate->was_overriden_ = true;
+  tls_delegate.Get().Set(delegate);
+  delegate->bound_ = true;
+
+  return std::make_pair(&delegate->client_interface_, overriden_delegate);
+}
+
 RunLoop::RunLoop(Type type)
     : delegate_(tls_delegate.Get().Get()),
       type_(type),
diff --git a/base/run_loop.h b/base/run_loop.h
index 57aae610..bdaeda5 100644
--- a/base/run_loop.h
+++ b/base/run_loop.h
@@ -5,6 +5,7 @@
 #ifndef BASE_RUN_LOOP_H_
 #define BASE_RUN_LOOP_H_
 
+#include <utility>
 #include <vector>
 
 #include "base/base_export.h"
@@ -159,10 +160,11 @@
   class BASE_EXPORT Delegate {
    public:
     Delegate();
-    ~Delegate();
+    virtual ~Delegate();
 
     // The client interface provided back to the caller who registers this
-    // Delegate via RegisterDelegateForCurrentThread.
+    // Delegate via RegisterDelegateForCurrentThread() or
+    // OverrideDelegateForCurrentThreadForTesting().
     class BASE_EXPORT Client {
      public:
       // Returns true if the Delegate should return from the topmost Run() when
@@ -170,11 +172,6 @@
       // becomes idle.
       bool ShouldQuitWhenIdle() const;
 
-      // Returns true if this |outer_| is currently in nested runs. This is a
-      // shortcut for RunLoop::IsNestedOnCurrentThread() for the owner of this
-      // interface.
-      bool IsNested() const;
-
      private:
       // Only a Delegate can instantiate a Delegate::Client.
       friend class Delegate;
@@ -221,6 +218,12 @@
     RunLoopStack active_run_loops_;
     ObserverList<RunLoop::NestingObserver> nesting_observers_;
 
+    // True if this Delegate was overriden through
+    // OverrideDelegateForCurrentThreadForTesting(). It will from then on always
+    // return from Run() when idle (i.e. its Client's ShouldQuitWhenIdle() will
+    // always be true).
+    bool was_overriden_ = false;
+
 #if DCHECK_IS_ON()
     bool allow_running_for_testing_ = true;
 #endif
@@ -243,6 +246,15 @@
   // Delegate::Client is valid as long as |delegate| is kept alive.
   static Delegate::Client* RegisterDelegateForCurrentThread(Delegate* delegate);
 
+  // Akin to RegisterDelegateForCurrentThread but overrides an existing Delegate
+  // (there must be one). Returning |delegate|'s client interface like
+  // RegisterDelegateForCurrentThread() as well as the overriden Delegate which
+  // the caller is now in charge of driving. The overriden Delegate's Run()
+  // method will always return when idle (or earlier if the Delegate's Quit()
+  // method is explicitly invoked).
+  static std::pair<Delegate::Client*, Delegate*>
+  OverrideDelegateForCurrentThreadForTesting(Delegate* delegate);
+
   // Quits the active RunLoop (when idle) -- there must be one. These were
   // introduced as prefered temporary replacements to the long deprecated
   // MessageLoop::Quit(WhenIdle) methods. Callers should properly plumb a
diff --git a/base/run_loop_unittest.cc b/base/run_loop_unittest.cc
index beebda3..1f626ca 100644
--- a/base/run_loop_unittest.cc
+++ b/base/run_loop_unittest.cc
@@ -87,7 +87,7 @@
     return origin_thread_checker_.CalledOnValidThread();
   }
 
-  bool ProcessTask() {
+  bool ProcessSingleTask() {
     OnceClosure task;
     {
       AutoLock auto_lock(tasks_lock_);
@@ -97,11 +97,18 @@
       pending_tasks_.pop();
     }
     // It's important to Run() after pop() and outside the lock as |task| may
-    // run a nested loop which will re-enter ProcessTask().
+    // run a nested loop which will re-enter ProcessSingleTask().
     std::move(task).Run();
     return true;
   }
 
+  base::queue<OnceClosure> TakePendingTasks() {
+    AutoLock auto_lock(tasks_lock_);
+    base::queue<OnceClosure> pending_tasks;
+    std::swap(pending_tasks, pending_tasks_);
+    return pending_tasks;
+  }
+
  private:
   ~SimpleSingleThreadTaskRunner() override = default;
 
@@ -116,49 +123,66 @@
   DISALLOW_COPY_AND_ASSIGN(SimpleSingleThreadTaskRunner);
 };
 
-// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
-// other base constructs.
-class TestDelegate final : public RunLoop::Delegate {
+// The basis of all TestDelegates, allows safely injecting a OnceClosure to be
+// run in the next idle phase of this delegate's Run() implementation. This can
+// be used to have code run on a thread that is otherwise livelocked in an idle
+// phase (sometimes a simple PostTask() won't do it -- e.g. when processing
+// application tasks is disallowed).
+class InjectableTestDelegate : public RunLoop::Delegate {
  public:
-  TestDelegate() = default;
+  void InjectClosureOnDelegate(OnceClosure closure) {
+    AutoLock auto_lock(closure_lock_);
+    closure_ = std::move(closure);
+  }
 
+  bool RunInjectedClosure() {
+    AutoLock auto_lock(closure_lock_);
+    if (closure_.is_null())
+      return false;
+    std::move(closure_).Run();
+    return true;
+  }
+
+ private:
+  Lock closure_lock_;
+  OnceClosure closure_;
+};
+
+// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
+// other base constructs. BindToCurrentThread() must be called before this
+// TestBoundDelegate is operational.
+class TestBoundDelegate final : public InjectableTestDelegate {
+ public:
+  TestBoundDelegate() = default;
+
+  // Makes this TestBoundDelegate become the RunLoop::Delegate and
+  // ThreadTaskRunnerHandle for this thread.
   void BindToCurrentThread() {
+    DCHECK(!run_loop_client_);
     thread_task_runner_handle_ =
         std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
     run_loop_client_ = RunLoop::RegisterDelegateForCurrentThread(this);
   }
 
-  // Runs |closure| on the TestDelegate thread as part of Run(). Useful to
-  // inject code in an otherwise livelocked Run() state.
-  void RunClosureOnDelegate(OnceClosure closure) {
-    AutoLock auto_lock(closure_lock_);
-    closure_ = std::move(closure);
-  }
-
  private:
   void Run(bool application_tasks_allowed) override {
     if (nested_run_allowing_tasks_incoming_) {
-      EXPECT_TRUE(run_loop_client_->IsNested());
+      EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
       EXPECT_TRUE(application_tasks_allowed);
-    } else if (run_loop_client_->IsNested()) {
+    } else if (RunLoop::IsNestedOnCurrentThread()) {
       EXPECT_FALSE(application_tasks_allowed);
     }
     nested_run_allowing_tasks_incoming_ = false;
 
     while (!should_quit_) {
-      if (application_tasks_allowed && simple_task_runner_->ProcessTask())
+      if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
         continue;
 
       if (run_loop_client_->ShouldQuitWhenIdle())
         break;
 
-      {
-        AutoLock auto_lock(closure_lock_);
-        if (!closure_.is_null()) {
-          std::move(closure_).Run();
-          continue;
-        }
-      }
+      if (RunInjectedClosure())
+        continue;
 
       PlatformThread::YieldCurrentThread();
     }
@@ -177,12 +201,83 @@
 
   scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
       MakeRefCounted<SimpleSingleThreadTaskRunner>();
+
   std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
 
   bool should_quit_ = false;
 
-  Lock closure_lock_;
-  OnceClosure closure_;
+  RunLoop::Delegate::Client* run_loop_client_ = nullptr;
+};
+
+// A test RunLoop::Delegate meant to override an existing RunLoop::Delegate.
+// TakeOverCurrentThread() must be called before this TestBoundDelegate is
+// operational.
+class TestOverridingDelegate final : public InjectableTestDelegate {
+ public:
+  TestOverridingDelegate() = default;
+
+  // Overrides the existing RunLoop::Delegate and ThreadTaskRunnerHandles on
+  // this thread with this TestOverridingDelegate's.
+  void TakeOverCurrentThread() {
+    DCHECK(!run_loop_client_);
+
+    overriden_task_runner_ = ThreadTaskRunnerHandle::Get();
+    DCHECK(overriden_task_runner_);
+    thread_task_runner_handle_override_scope_ =
+        ThreadTaskRunnerHandle::OverrideForTesting(
+            simple_task_runner_,
+            ThreadTaskRunnerHandle::OverrideType::kTakeOverThread);
+
+    auto delegate_override_pair =
+        RunLoop::OverrideDelegateForCurrentThreadForTesting(this);
+    run_loop_client_ = delegate_override_pair.first;
+    overriden_delegate_ = delegate_override_pair.second;
+    DCHECK(overriden_delegate_);
+  }
+
+ private:
+  void Run(bool application_tasks_allowed) override {
+    while (!should_quit_) {
+      auto pending_tasks = simple_task_runner_->TakePendingTasks();
+      if (!pending_tasks.empty()) {
+        while (!pending_tasks.empty()) {
+          overriden_task_runner_->PostTask(FROM_HERE,
+                                           std::move(pending_tasks.front()));
+          pending_tasks.pop();
+        }
+        overriden_delegate_->Run(application_tasks_allowed);
+        continue;
+      }
+
+      if (run_loop_client_->ShouldQuitWhenIdle())
+        break;
+
+      if (RunInjectedClosure())
+        continue;
+
+      PlatformThread::YieldCurrentThread();
+    }
+    should_quit_ = false;
+  }
+
+  void Quit() override {
+    should_quit_ = true;
+    overriden_delegate_->Quit();
+  }
+
+  void EnsureWorkScheduled() override {
+    overriden_delegate_->EnsureWorkScheduled();
+  }
+
+  scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
+      MakeRefCounted<SimpleSingleThreadTaskRunner>();
+
+  ScopedClosureRunner thread_task_runner_handle_override_scope_;
+
+  scoped_refptr<SingleThreadTaskRunner> overriden_task_runner_;
+  RunLoop::Delegate* overriden_delegate_;
+
+  bool should_quit_ = false;
 
   RunLoop::Delegate::Client* run_loop_client_ = nullptr;
 };
@@ -195,6 +290,10 @@
   // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
   // delegate interface fully works standalone.
   kTestDelegate,
+
+  // Runs all RunLoopTests through a RunLoop::Delegate which overrides a
+  // kRealEnvironment's registered RunLoop::Delegate.
+  kOverridingTestDelegate,
 };
 
 // The task environment for the RunLoopTest of a given type. A separate class
@@ -203,20 +302,31 @@
  public:
   RunLoopTestEnvironment(RunLoopTestType type) {
     switch (type) {
-      case RunLoopTestType::kRealEnvironment:
+      case RunLoopTestType::kRealEnvironment: {
         task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
         break;
-      case RunLoopTestType::kTestDelegate:
-        test_delegate_ = std::make_unique<TestDelegate>();
-        test_delegate_->BindToCurrentThread();
+      }
+      case RunLoopTestType::kTestDelegate: {
+        auto test_delegate = std::make_unique<TestBoundDelegate>();
+        test_delegate->BindToCurrentThread();
+        test_delegate_ = std::move(test_delegate);
         break;
+      }
+      case RunLoopTestType::kOverridingTestDelegate: {
+        task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
+        auto test_delegate = std::make_unique<TestOverridingDelegate>();
+        test_delegate->TakeOverCurrentThread();
+        test_delegate_ = std::move(test_delegate);
+        break;
+      }
     }
   }
 
  private:
-  // Instantiates one or the other based on the RunLoopTestType.
+  // Instantiates one or the other based on the RunLoopTestType (or both in the
+  // kOverridingTestDelegate case).
   std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
-  std::unique_ptr<TestDelegate> test_delegate_;
+  std::unique_ptr<InjectableTestDelegate> test_delegate_;
 };
 
 class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
@@ -539,15 +649,19 @@
 INSTANTIATE_TEST_CASE_P(Mock,
                         RunLoopTest,
                         testing::Values(RunLoopTestType::kTestDelegate));
+INSTANTIATE_TEST_CASE_P(
+    OverridingMock,
+    RunLoopTest,
+    testing::Values(RunLoopTestType::kOverridingTestDelegate));
 
 TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
-  TestDelegate unbound_test_delegate_;
+  TestBoundDelegate unbound_test_delegate_;
   // Exercise the DCHECK in RunLoop::RunLoop().
   EXPECT_DCHECK_DEATH({ RunLoop(); });
 }
 
 TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
-  TestDelegate test_delegate;
+  TestBoundDelegate test_delegate;
   test_delegate.BindToCurrentThread();
 
   base::Thread other_thread("test");
@@ -599,8 +713,8 @@
   other_thread.task_runner()->PostDelayedTask(
       FROM_HERE,
       BindOnce(
-          [](TestDelegate* test_delegate, OnceClosure injected_closure) {
-            test_delegate->RunClosureOnDelegate(std::move(injected_closure));
+          [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
+            test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
           },
           Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
       TestTimeouts::tiny_timeout());
diff --git a/base/threading/thread_task_runner_handle.cc b/base/threading/thread_task_runner_handle.cc
index 1d9756f..1e27675d 100644
--- a/base/threading/thread_task_runner_handle.cc
+++ b/base/threading/thread_task_runner_handle.cc
@@ -39,7 +39,8 @@
 
 // static
 ScopedClosureRunner ThreadTaskRunnerHandle::OverrideForTesting(
-    scoped_refptr<SingleThreadTaskRunner> overriding_task_runner) {
+    scoped_refptr<SingleThreadTaskRunner> overriding_task_runner,
+    ThreadTaskRunnerHandle::OverrideType type) {
   // OverrideForTesting() is not compatible with a SequencedTaskRunnerHandle
   // being set (but SequencedTaskRunnerHandle::IsSet() includes
   // ThreadTaskRunnerHandle::IsSet() so that's discounted as the only valid
@@ -67,7 +68,9 @@
   ttrh->task_runner_.swap(overriding_task_runner);
 
   auto no_running_during_override =
-      std::make_unique<RunLoop::ScopedDisallowRunningForTesting>();
+      type == OverrideType::kTakeOverThread
+          ? nullptr
+          : std::make_unique<RunLoop::ScopedDisallowRunningForTesting>();
 
   return ScopedClosureRunner(base::Bind(
       [](scoped_refptr<SingleThreadTaskRunner> task_runner_to_restore,
diff --git a/base/threading/thread_task_runner_handle.h b/base/threading/thread_task_runner_handle.h
index 480a03c..a24d68b 100644
--- a/base/threading/thread_task_runner_handle.h
+++ b/base/threading/thread_task_runner_handle.h
@@ -34,9 +34,19 @@
   // ScopedClosureRunners expire in LIFO (stack) order. Note: nesting
   // ThreadTaskRunnerHandles isn't generally desired but it's useful in unit
   // tests where multiple task runners can share the main thread for simplicity
-  // and determinism.
+  // and determinism (in which case RunLoop::Run() is banned for the scope of
+  // the override as it would execute tasks from the wrong task runner). It's
+  // also useful in unit test frameworks in which a task runner takes over the
+  // main thread; in that case it's fine to allow running through
+  // |type = kTakeOverThread| iff RunLoop::Run() will result in running tasks
+  // posted to the overriding ThreadTaskRunnerHandle.
+  enum class OverrideType {
+    kDefault,
+    kTakeOverThread,
+  };
   static ScopedClosureRunner OverrideForTesting(
-      scoped_refptr<SingleThreadTaskRunner> overriding_task_runner);
+      scoped_refptr<SingleThreadTaskRunner> overriding_task_runner,
+      OverrideType type = OverrideType::kDefault);
 
   // Binds |task_runner| to the current thread. |task_runner| must belong
   // to the current thread for this to succeed.