Add support for base::Closure in the MessageLoop, and reimplement the whole sucker on top of base::Closure.  After this, all Task objects that are posted will be wrapped in a closure prior to dispatch.

BUG=35223
TEST=unittests.

Review URL: http://codereview.chromium.org/6463013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82300 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index cd681f37..be40f39 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -4,6 +4,9 @@
 
 #include <vector>
 
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
 #include "base/eintr_wrapper.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
@@ -25,6 +28,7 @@
 using base::Thread;
 using base::Time;
 using base::TimeDelta;
+using base::TimeTicks;
 
 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
 // to avoid chopping this file up with so many #ifdefs.
@@ -80,19 +84,9 @@
   std::string result_;
 };
 
-class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> {
- public:
-  void QuitNow() {
-    MessageLoop::current()->Quit();
-  }
-
- private:
-  friend class base::RefCounted<QuitMsgLoop>;
-
-  ~QuitMsgLoop() {}
-};
-
-void RunTest_PostTask(MessageLoop::Type message_loop_type) {
+// TODO(ajwong): Remove this once we've finished getting rid of the PostTask()
+// compatibility methods.
+void RunTest_PostLegacyTask(MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   // Add tests to message loop
@@ -112,9 +106,38 @@
     foo.get(), &Foo::Test2Mixed, a, &d));
 
   // After all tests, post a message that will shut down the message loop
-  scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop());
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      quit.get(), &QuitMsgLoop::QuitNow));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
+
+  // Now kick things off
+  MessageLoop::current()->Run();
+
+  EXPECT_EQ(foo->test_count(), 105);
+  EXPECT_EQ(foo->result(), "abacad");
+}
+
+void RunTest_PostTask(MessageLoop::Type message_loop_type) {
+  MessageLoop loop(message_loop_type);
+
+  // Add tests to message loop
+  scoped_refptr<Foo> foo(new Foo());
+  std::string a("a"), b("b"), c("c"), d("d");
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test0, foo.get()));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+    &Foo::Test1ConstRef, foo.get(), a));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test1Ptr, foo.get(), &b));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test1Int, foo.get(), 100));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test2Ptr, foo.get(), &a, &c));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test2Mixed, foo.get(), a, &d));
+
+  // After all tests, post a message that will shut down the message loop
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
 
   // Now kick things off
   MessageLoop::current()->Run();
@@ -129,23 +152,22 @@
   // Add tests to message loop
   scoped_refptr<Foo> foo(new Foo());
   std::string a("a"), b("b"), c("c"), d("d");
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test0));
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test1ConstRef, a));
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test1Ptr, &b));
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test1Int, 100));
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test2Ptr, &a, &c));
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      foo.get(), &Foo::Test2Mixed, a, &d));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test0, foo.get()));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test1ConstRef, foo.get(), a));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test1Ptr, foo.get(), &b));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test1Int, foo.get(), 100));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test2Ptr, foo.get(), &a, &c));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &Foo::Test2Mixed, foo.get(), a, &d));
 
   // After all tests, post a message that will shut down the message loop
-  scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop());
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      quit.get(), &QuitMsgLoop::QuitNow));
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
 
   // Now kick things off with the SEH block active.
   MessageLoop::current()->set_exception_restoration(true);
@@ -156,39 +178,23 @@
   EXPECT_EQ(foo->result(), "abacad");
 }
 
-// This class runs slowly to simulate a large amount of work being done.
-class SlowTask : public Task {
- public:
-  SlowTask(int pause_ms, int* quit_counter)
-      : pause_ms_(pause_ms), quit_counter_(quit_counter) {
-  }
-  virtual void Run() {
-    PlatformThread::Sleep(pause_ms_);
-    if (--(*quit_counter_) == 0)
+// This function runs slowly to simulate a large amount of work being done.
+static void SlowFunc(int pause_ms, int* quit_counter) {
+    PlatformThread::Sleep(pause_ms);
+    if (--(*quit_counter) == 0)
       MessageLoop::current()->Quit();
-  }
- private:
-  int pause_ms_;
-  int* quit_counter_;
-};
+}
 
-// This class records the time when Run was called in a Time object, which is
+// This function records the time when Run was called in a Time object, which is
 // useful for building a variety of MessageLoop tests.
-class RecordRunTimeTask : public SlowTask {
- public:
-  RecordRunTimeTask(Time* run_time, int* quit_counter)
-      : SlowTask(10, quit_counter), run_time_(run_time) {
-  }
-  virtual void Run() {
-    *run_time_ = Time::Now();
+static void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
+  *run_time = Time::Now();
+
     // Cause our Run function to take some time to execute.  As a result we can
-    // count on subsequent RecordRunTimeTask objects running at a future time,
+    // count on subsequent RecordRunTimeFunc()s running at a future time,
     // without worry about the resolution of our system clock being an issue.
-    SlowTask::Run();
-  }
- private:
-  Time* run_time_;
-};
+  SlowFunc(10, quit_counter);
+}
 
 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
@@ -201,7 +207,8 @@
   Time run_time;
 
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
+      kDelayMS);
 
   Time time_before_run = Time::Now();
   loop.Run();
@@ -211,20 +218,20 @@
   EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds());
 }
 
-void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) {
+void RunTest_PostDelayedTask_InDelayOrder(
+    MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   // Test that two tasks with different delays run in the right order.
-
   int num_tasks = 2;
   Time run_time1, run_time2;
 
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 200);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), 200);
   // If we get a large pause in execution (due to a context switch) here, this
   // test could fail.
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10);
 
   loop.Run();
   EXPECT_EQ(0, num_tasks);
@@ -232,7 +239,8 @@
   EXPECT_TRUE(run_time2 < run_time1);
 }
 
-void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) {
+void RunTest_PostDelayedTask_InPostOrder(
+    MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   // Test that two tasks with the same delay run in the order in which they
@@ -249,9 +257,11 @@
   Time run_time1, run_time2;
 
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), kDelayMS);
+      FROM_HERE,
+      base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelayMS);
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), kDelayMS);
+      FROM_HERE,
+      base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelayMS);
 
   loop.Run();
   EXPECT_EQ(0, num_tasks);
@@ -271,10 +281,9 @@
   int num_tasks = 2;
   Time run_time;
 
-  loop.PostTask(
-      FROM_HERE, new SlowTask(kPauseMS, &num_tasks));
+  loop.PostTask(FROM_HERE, base::Bind(&SlowFunc, kPauseMS, &num_tasks));
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks), 10);
 
   Time time_before_run = Time::Now();
   loop.Run();
@@ -300,10 +309,11 @@
 
   // Clutter the ML with tasks.
   for (int i = 1; i < num_tasks; ++i)
-    loop.PostTask(FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks));
+    loop.PostTask(FROM_HERE,
+                  base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks));
 
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 1);
 
   loop.Run();
   EXPECT_EQ(0, num_tasks);
@@ -311,7 +321,8 @@
   EXPECT_TRUE(run_time2 > run_time1);
 }
 
-void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) {
+void RunTest_PostDelayedTask_SharedTimer(
+    MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   // Test that the interval of the timer, used to run the next delayed task, is
@@ -323,9 +334,11 @@
   Time run_time1, run_time2;
 
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 1000000);
+      FROM_HERE,
+      base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks),
+      1000000);
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10);
+      FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10);
 
   Time start_time = Time::Now();
 
@@ -348,27 +361,15 @@
 
 #if defined(OS_WIN)
 
-class SubPumpTask : public Task {
- public:
-  virtual void Run() {
-    MessageLoop::current()->SetNestableTasksAllowed(true);
-    MSG msg;
-    while (GetMessage(&msg, NULL, 0, 0)) {
-      TranslateMessage(&msg);
-      DispatchMessage(&msg);
-    }
-    MessageLoop::current()->Quit();
+void SubPumpFunc() {
+  MessageLoop::current()->SetNestableTasksAllowed(true);
+  MSG msg;
+  while (GetMessage(&msg, NULL, 0, 0)) {
+    TranslateMessage(&msg);
+    DispatchMessage(&msg);
   }
-};
-
-class SubPumpQuitTask : public Task {
- public:
-  SubPumpQuitTask() {
-  }
-  virtual void Run() {
-    PostQuitMessage(0);
-  }
-};
+  MessageLoop::current()->Quit();
+}
 
 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
   MessageLoop loop(MessageLoop::TYPE_UI);
@@ -381,15 +382,16 @@
   int num_tasks = 1;
   Time run_time;
 
-  loop.PostTask(FROM_HERE, new SubPumpTask());
+  loop.PostTask(FROM_HERE, base::Bind(&SubPumpFunc));
 
   // This very delayed task should never run.
   loop.PostDelayedTask(
-      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000);
+      FROM_HERE,
+      base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
+      1000000);
 
-  // This slightly delayed task should run from within SubPumpTask::Run().
-  loop.PostDelayedTask(
-      FROM_HERE, new SubPumpQuitTask(), 10);
+  // This slightly delayed task should run from within SubPumpFunc).
+  loop.PostDelayedTask(FROM_HERE, base::Bind(&PostQuitMessage, 0), 10);
 
   Time start_time = Time::Now();
 
@@ -411,69 +413,73 @@
 
 #endif  // defined(OS_WIN)
 
-class RecordDeletionTask : public Task {
+// This is used to inject a test point for recording the destructor calls for
+// Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
+// are trying to hook the actual destruction, which is not a common operation.
+class RecordDeletionProbe : public base::RefCounted<RecordDeletionProbe> {
  public:
-  RecordDeletionTask(Task* post_on_delete, bool* was_deleted)
+  RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
       : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
   }
-  ~RecordDeletionTask() {
+  ~RecordDeletionProbe() {
     *was_deleted_ = true;
     if (post_on_delete_)
-      MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_);
+      MessageLoop::current()->PostTask(
+          FROM_HERE,
+          base::Bind(&RecordDeletionProbe::Run, post_on_delete_.get()));
   }
   virtual void Run() {}
  private:
-  Task* post_on_delete_;
+  scoped_refptr<RecordDeletionProbe> post_on_delete_;
   bool* was_deleted_;
 };
 
-void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) {
+void RunTest_EnsureDeletion(MessageLoop::Type message_loop_type) {
   bool a_was_deleted = false;
   bool b_was_deleted = false;
   {
     MessageLoop loop(message_loop_type);
     loop.PostTask(
-        FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted));
+        FROM_HERE, base::Bind(&RecordDeletionProbe::Run,
+                              new RecordDeletionProbe(NULL, &a_was_deleted)));
     loop.PostDelayedTask(
-        FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000);
+        FROM_HERE, base::Bind(&RecordDeletionProbe::Run,
+                              new RecordDeletionProbe(NULL, &b_was_deleted)),
+        1000);  // TODO(ajwong): Do we really need 1000ms here?
   }
   EXPECT_TRUE(a_was_deleted);
   EXPECT_TRUE(b_was_deleted);
 }
 
-void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type) {
+void RunTest_EnsureDeletion_Chain(MessageLoop::Type message_loop_type) {
   bool a_was_deleted = false;
   bool b_was_deleted = false;
   bool c_was_deleted = false;
   {
     MessageLoop loop(message_loop_type);
-    RecordDeletionTask* a = new RecordDeletionTask(NULL, &a_was_deleted);
-    RecordDeletionTask* b = new RecordDeletionTask(a, &b_was_deleted);
-    RecordDeletionTask* c = new RecordDeletionTask(b, &c_was_deleted);
-    loop.PostTask(FROM_HERE, c);
+    // The scoped_refptr for each of the below is held either by the chained
+    // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
+    RecordDeletionProbe* a = new RecordDeletionProbe(NULL, &a_was_deleted);
+    RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
+    RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
+    loop.PostTask(FROM_HERE, base::Bind(&RecordDeletionProbe::Run, c));
   }
   EXPECT_TRUE(a_was_deleted);
   EXPECT_TRUE(b_was_deleted);
   EXPECT_TRUE(c_was_deleted);
 }
 
-class NestingTest : public Task {
- public:
-  explicit NestingTest(int* depth) : depth_(depth) {
-  }
-  void Run() {
-    if (*depth_ > 0) {
-      *depth_ -= 1;
-      MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_));
+void NestingFunc(int* depth) {
+  if (*depth > 0) {
+    *depth -= 1;
+    MessageLoop::current()->PostTask(FROM_HERE,
+                                     base::Bind(&NestingFunc, depth));
 
-      MessageLoop::current()->SetNestableTasksAllowed(true);
-      MessageLoop::current()->Run();
-    }
-    MessageLoop::current()->Quit();
+    MessageLoop::current()->SetNestableTasksAllowed(true);
+    MessageLoop::current()->Run();
   }
- private:
-  int* depth_;
-};
+  MessageLoop::current()->Quit();
+}
 
 #if defined(OS_WIN)
 
@@ -485,13 +491,14 @@
 
 // This task throws an SEH exception: initially write to an invalid address.
 // If the right SEH filter is installed, it will fix the error.
-class CrasherTask : public Task {
+class Crasher : public base::RefCounted<Crasher> {
  public:
   // Ctor. If trash_SEH_handler is true, the task will override the unhandled
   // exception handler with one sure to crash this test.
-  explicit CrasherTask(bool trash_SEH_handler)
+  explicit Crasher(bool trash_SEH_handler)
       : trash_SEH_handler_(trash_SEH_handler) {
   }
+
   void Run() {
     PlatformThread::Sleep(1);
     if (trash_SEH_handler_)
@@ -502,7 +509,7 @@
 #if defined(_M_IX86)
 
     __asm {
-      mov eax, dword ptr [CrasherTask::bad_array_]
+      mov eax, dword ptr [Crasher::bad_array_]
       mov byte ptr [eax], 66
     }
 
@@ -527,17 +534,17 @@
   static char valid_store_;
 };
 
-volatile char* CrasherTask::bad_array_ = 0;
-char CrasherTask::valid_store_ = 0;
+volatile char* Crasher::bad_array_ = 0;
+char Crasher::valid_store_ = 0;
 
 // This SEH filter fixes the problem and retries execution. Fixing requires
-// that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried
+// that the last instruction: mov eax, [Crasher::bad_array_] to be retried
 // so we move the instruction pointer 5 bytes back.
-LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) {
+LONG WINAPI HandleCrasherException(EXCEPTION_POINTERS *ex_info) {
   if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
     return EXCEPTION_EXECUTE_HANDLER;
 
-  CrasherTask::FixError();
+  Crasher::FixError();
 
 #if defined(_M_IX86)
 
@@ -559,9 +566,11 @@
     return;
 
   LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
-      ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
+      ::SetUnhandledExceptionFilter(&HandleCrasherException);
 
-  MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(false));
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&Crasher::Run, new Crasher(false)));
   MessageLoop::current()->set_exception_restoration(true);
   MessageLoop::current()->Run();
   MessageLoop::current()->set_exception_restoration(false);
@@ -576,9 +585,11 @@
     return;
 
   LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
-      ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
+      ::SetUnhandledExceptionFilter(&HandleCrasherException);
 
-  MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(true));
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&Crasher::Run, new Crasher(true)));
   MessageLoop::current()->set_exception_restoration(true);
   MessageLoop::current()->Run();
   MessageLoop::current()->set_exception_restoration(false);
@@ -592,7 +603,8 @@
   MessageLoop loop(message_loop_type);
 
   int depth = 100;
-  MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth));
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&NestingFunc, &depth));
   MessageLoop::current()->Run();
   EXPECT_EQ(depth, 0);
 }
@@ -627,8 +639,6 @@
   }
 };
 
-typedef std::vector<TaskItem> TaskList;
-
 std::ostream& operator <<(std::ostream& os, TaskType type) {
   switch (type) {
   case MESSAGEBOX:        os << "MESSAGEBOX"; break;
@@ -654,223 +664,141 @@
     return os << item.type << " " << item.cookie << " ends";
 }
 
-// Saves the order the tasks ran.
-class OrderedTasks : public Task {
+class TaskList {
  public:
-  OrderedTasks(TaskList* order, int cookie)
-      : order_(order),
-        type_(ORDERERD),
-        cookie_(cookie) {
-  }
-  OrderedTasks(TaskList* order, TaskType type, int cookie)
-      : order_(order),
-        type_(type),
-        cookie_(cookie) {
-  }
-
-  void RunStart() {
-    TaskItem item(type_, cookie_, true);
+  void RecordStart(TaskType type, int cookie) {
+    TaskItem item(type, cookie, true);
     DVLOG(1) << item;
-    order_->push_back(item);
+    task_list_.push_back(item);
   }
-  void RunEnd() {
-    TaskItem item(type_, cookie_, false);
+
+  void RecordEnd(TaskType type, int cookie) {
+    TaskItem item(type, cookie, false);
     DVLOG(1) << item;
-    order_->push_back(item);
+    task_list_.push_back(item);
   }
 
-  virtual void Run() {
-    RunStart();
-    RunEnd();
+  size_t Size() {
+    return task_list_.size();
   }
 
- protected:
-  TaskList* order() const {
-    return order_;
-  }
-
-  int cookie() const {
-    return cookie_;
+  TaskItem Get(int n)  {
+    return task_list_[n];
   }
 
  private:
-  TaskList* order_;
-  TaskType type_;
-  int cookie_;
+  std::vector<TaskItem> task_list_;
 };
 
+// Saves the order the tasks ran.
+void OrderedFunc(TaskList* order, int cookie) {
+  order->RecordStart(ORDERERD, cookie);
+  order->RecordEnd(ORDERERD, cookie);
+}
+
 #if defined(OS_WIN)
 
 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
 // common controls (like OpenFile) and StartDoc printing function can cause
 // implicit message loops.
-class MessageBoxTask : public OrderedTasks {
- public:
-  MessageBoxTask(TaskList* order, int cookie, bool is_reentrant)
-      : OrderedTasks(order, MESSAGEBOX, cookie),
-        is_reentrant_(is_reentrant) {
-  }
-
-  virtual void Run() {
-    RunStart();
-    if (is_reentrant_)
-      MessageLoop::current()->SetNestableTasksAllowed(true);
-    MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
-    RunEnd();
-  }
-
- private:
-  bool is_reentrant_;
-};
+void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
+  order->RecordStart(MESSAGEBOX, cookie);
+  if (is_reentrant)
+    MessageLoop::current()->SetNestableTasksAllowed(true);
+  MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
+  order->RecordEnd(MESSAGEBOX, cookie);
+}
 
 // Will end the MessageBox.
-class EndDialogTask : public OrderedTasks {
- public:
-  EndDialogTask(TaskList* order, int cookie)
-      : OrderedTasks(order, ENDDIALOG, cookie) {
+void EndDialogFunc(TaskList* order, int cookie) {
+  order->RecordStart(ENDDIALOG, cookie);
+  HWND window = GetActiveWindow();
+  if (window != NULL) {
+    EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
+    // Cheap way to signal that the window wasn't found if RunEnd() isn't
+    // called.
+    order->RecordEnd(ENDDIALOG, cookie);
   }
-
-  virtual void Run() {
-    RunStart();
-    HWND window = GetActiveWindow();
-    if (window != NULL) {
-      EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
-      // Cheap way to signal that the window wasn't found if RunEnd() isn't
-      // called.
-      RunEnd();
-    }
-  }
-};
+}
 
 #endif  // defined(OS_WIN)
 
-class RecursiveTask : public OrderedTasks {
- public:
-  RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant)
-      : OrderedTasks(order, RECURSIVE, cookie),
-        depth_(depth),
-        is_reentrant_(is_reentrant) {
+void RecursiveFunc(TaskList* order, int cookie, int depth,
+                   bool is_reentrant) {
+  order->RecordStart(RECURSIVE, cookie);
+  if (depth > 0) {
+    if (is_reentrant)
+      MessageLoop::current()->SetNestableTasksAllowed(true);
+    MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
   }
+  order->RecordEnd(RECURSIVE, cookie);
+}
 
-  virtual void Run() {
-    RunStart();
-    if (depth_ > 0) {
-      if (is_reentrant_)
-        MessageLoop::current()->SetNestableTasksAllowed(true);
-      MessageLoop::current()->PostTask(FROM_HERE,
-          new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_));
-    }
-    RunEnd();
-  }
+void RecursiveSlowFunc(TaskList* order, int cookie, int depth,
+                       bool is_reentrant) {
+  RecursiveFunc(order, cookie, depth, is_reentrant);
+  PlatformThread::Sleep(10);  // milliseconds
+}
 
- private:
-  int depth_;
-  bool is_reentrant_;
-};
+void QuitFunc(TaskList* order, int cookie) {
+  order->RecordStart(QUITMESSAGELOOP, cookie);
+  MessageLoop::current()->Quit();
+  order->RecordEnd(QUITMESSAGELOOP, cookie);
+}
 
-class RecursiveSlowTask : public RecursiveTask {
- public:
-  RecursiveSlowTask(int depth, TaskList* order, int cookie, bool is_reentrant)
-      : RecursiveTask(depth, order, cookie, is_reentrant) {
-  }
-
-  virtual void Run() {
-    RecursiveTask::Run();
-    PlatformThread::Sleep(10);  // milliseconds
-  }
-};
-
-class QuitTask : public OrderedTasks {
- public:
-  QuitTask(TaskList* order, int cookie)
-      : OrderedTasks(order, QUITMESSAGELOOP, cookie) {
-  }
-
-  virtual void Run() {
-    RunStart();
-    MessageLoop::current()->Quit();
-    RunEnd();
-  }
-};
-
-class SleepTask : public OrderedTasks {
- public:
-  SleepTask(TaskList* order, int cookie, int ms)
-      : OrderedTasks(order, SLEEP, cookie), ms_(ms) {
-  }
-
-  virtual void Run() {
-    RunStart();
-    PlatformThread::Sleep(ms_);
-    RunEnd();
-  }
-
- private:
-  int ms_;
-};
+void SleepFunc(TaskList* order, int cookie, int ms) {
+  order->RecordStart(SLEEP, cookie);
+  PlatformThread::Sleep(ms);
+  order->RecordEnd(SLEEP, cookie);
+}
 
 #if defined(OS_WIN)
+void RecursiveFuncWin(MessageLoop* target,
+                      HANDLE event,
+                      bool expect_window,
+                      TaskList* order,
+                      bool is_reentrant) {
+  target->PostTask(FROM_HERE,
+                   base::Bind(&RecursiveFunc, order, 1, 2, is_reentrant));
+  target->PostTask(FROM_HERE,
+                   base::Bind(&MessageBoxFunc, order, 2, is_reentrant));
+  target->PostTask(FROM_HERE,
+                   base::Bind(&RecursiveFunc, order, 3, 2, is_reentrant));
+  // The trick here is that for recursive task processing, this task will be
+  // ran _inside_ the MessageBox message loop, dismissing the MessageBox
+  // without a chance.
+  // For non-recursive task processing, this will be executed _after_ the
+  // MessageBox will have been dismissed by the code below, where
+  // expect_window_ is true.
+  target->PostTask(FROM_HERE,
+                   base::Bind(&EndDialogFunc, order, 4));
+  target->PostTask(FROM_HERE,
+                   base::Bind(&QuitFunc, order, 5));
 
-class Recursive2Tasks : public Task {
- public:
-  Recursive2Tasks(MessageLoop* target,
-                  HANDLE event,
-                  bool expect_window,
-                  TaskList* order,
-                  bool is_reentrant)
-      : target_(target),
-        event_(event),
-        expect_window_(expect_window),
-        order_(order),
-        is_reentrant_(is_reentrant) {
-  }
+  // Enforce that every tasks are sent before starting to run the main thread
+  // message loop.
+  ASSERT_TRUE(SetEvent(event));
 
-  virtual void Run() {
-    target_->PostTask(FROM_HERE,
-                      new RecursiveTask(2, order_, 1, is_reentrant_));
-    target_->PostTask(FROM_HERE,
-                      new MessageBoxTask(order_, 2, is_reentrant_));
-    target_->PostTask(FROM_HERE,
-                      new RecursiveTask(2, order_, 3, is_reentrant_));
-    // The trick here is that for recursive task processing, this task will be
-    // ran _inside_ the MessageBox message loop, dismissing the MessageBox
-    // without a chance.
-    // For non-recursive task processing, this will be executed _after_ the
-    // MessageBox will have been dismissed by the code below, where
-    // expect_window_ is true.
-    target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4));
-    target_->PostTask(FROM_HERE, new QuitTask(order_, 5));
-
-    // Enforce that every tasks are sent before starting to run the main thread
-    // message loop.
-    ASSERT_TRUE(SetEvent(event_));
-
-    // Poll for the MessageBox. Don't do this at home! At the speed we do it,
-    // you will never realize one MessageBox was shown.
-    for (; expect_window_;) {
-      HWND window = FindWindow(L"#32770", kMessageBoxTitle);
-      if (window) {
-        // Dismiss it.
-        for (;;) {
-          HWND button = FindWindowEx(window, NULL, L"Button", NULL);
-          if (button != NULL) {
-            EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
-            EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
-            break;
-          }
+  // Poll for the MessageBox. Don't do this at home! At the speed we do it,
+  // you will never realize one MessageBox was shown.
+  for (; expect_window;) {
+    HWND window = FindWindow(L"#32770", kMessageBoxTitle);
+    if (window) {
+      // Dismiss it.
+      for (;;) {
+        HWND button = FindWindowEx(window, NULL, L"Button", NULL);
+        if (button != NULL) {
+          EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
+          EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
+          break;
         }
-        break;
       }
+      break;
     }
   }
-
- private:
-  MessageLoop* target_;
-  HANDLE event_;
-  TaskList* order_;
-  bool expect_window_;
-  bool is_reentrant_;
-};
+}
 
 #endif  // defined(OS_WIN)
 
@@ -879,30 +807,34 @@
 
   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
   TaskList order;
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveTask(2, &order, 1, false));
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveTask(2, &order, 2, false));
-  MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3));
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&RecursiveFunc, &order, 1, 2, false));
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&RecursiveFunc, &order, 2, 2, false));
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&QuitFunc, &order, 3));
 
   MessageLoop::current()->Run();
 
   // FIFO order.
-  ASSERT_EQ(14U, order.size());
-  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
-  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
-  EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false));
+  ASSERT_EQ(14U, order.Size());
+  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
+  EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
+  EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
 }
 
 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) {
@@ -910,66 +842,66 @@
 
   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
   TaskList order;
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveSlowTask(2, &order, 1, false));
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveSlowTask(2, &order, 2, false));
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-                                          new OrderedTasks(&order, 3), 5);
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-                                          new QuitTask(&order, 4), 5);
+  MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 1, 2, false));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 2, 2, false));
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, base::Bind(&OrderedFunc, &order, 3), 5);
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, base::Bind(&QuitFunc, &order, 4), 5);
 
   MessageLoop::current()->Run();
 
   // FIFO order.
-  ASSERT_EQ(16U, order.size());
-  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 3, true));
-  EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 3, false));
-  EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 4, true));
-  EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 4, false));
-  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[14], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[15], TaskItem(RECURSIVE, 2, false));
+  ASSERT_EQ(16U, order.Size());
+  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 3, true));
+  EXPECT_EQ(order.Get(7), TaskItem(ORDERERD, 3, false));
+  EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
+  EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
+  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
 }
 
 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   TaskList order;
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveTask(2, &order, 1, true));
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new RecursiveTask(2, &order, 2, true));
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new QuitTask(&order, 3));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&RecursiveFunc, &order, 1, 2, true));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&RecursiveFunc, &order, 2, 2, true));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&QuitFunc, &order, 3));
 
   MessageLoop::current()->Run();
 
   // FIFO order.
-  ASSERT_EQ(14U, order.size());
-  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
-  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
-  EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false));
-  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true));
-  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false));
+  ASSERT_EQ(14U, order.Size());
+  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
+  EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
+  EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
+  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
+  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
 }
 
 #if defined(OS_WIN)
@@ -987,35 +919,36 @@
   TaskList order;
   base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
   worker.message_loop()->PostTask(FROM_HERE,
-                                  new Recursive2Tasks(MessageLoop::current(),
-                                                      event,
-                                                      true,
-                                                      &order,
-                                                      false));
+                                  base::Bind(&RecursiveFuncWin,
+                                             MessageLoop::current(),
+                                             event.Get(),
+                                             true,
+                                             &order,
+                                             false));
   // Let the other thread execute.
   WaitForSingleObject(event, INFINITE);
   MessageLoop::current()->Run();
 
-  ASSERT_EQ(order.size(), 17);
-  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true));
-  EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false));
-  EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false));
-  // When EndDialogTask is processed, the window is already dismissed, hence no
+  ASSERT_EQ(order.Size(), 17);
+  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
+  EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
+  EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
+  // When EndDialogFunc is processed, the window is already dismissed, hence no
   // "end" entry.
-  EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true));
-  EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true));
-  EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false));
-  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false));
-  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false));
+  EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
+  EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
+  EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
+  EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
+  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
 }
 
 // A side effect of this test is the generation a beep. Sorry.  This test also
@@ -1030,80 +963,78 @@
   TaskList order;
   base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
   worker.message_loop()->PostTask(FROM_HERE,
-                                  new Recursive2Tasks(MessageLoop::current(),
-                                                      event,
-                                                      false,
-                                                      &order,
-                                                      true));
+                                  base::Bind(&RecursiveFuncWin,
+                                             MessageLoop::current(),
+                                             event.Get(),
+                                             false,
+                                             &order,
+                                             true));
   // Let the other thread execute.
   WaitForSingleObject(event, INFINITE);
   MessageLoop::current()->Run();
 
-  ASSERT_EQ(order.size(), 18);
-  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true));
+  ASSERT_EQ(order.Size(), 18);
+  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
   // Note that this executes in the MessageBox modal loop.
-  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false));
-  EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true));
-  EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false));
-  EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false));
-  /* The order can subtly change here. The reason is that when RecursiveTask(1)
+  EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
+  EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
+  EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
+  EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
+  /* The order can subtly change here. The reason is that when RecursiveFunc(1)
      is called in the main thread, if it is faster than getting to the
-     PostTask(FROM_HERE, QuitTask) execution, the order of task execution can
-     change. We don't care anyway that the order isn't correct.
-  EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true));
-  EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false));
-  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
+     PostTask(FROM_HERE, base::Bind(&QuitFunc) execution, the order of task
+     execution can change. We don't care anyway that the order isn't correct.
+  EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
+  EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
+  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
   */
-  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false));
-  EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true));
-  EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false));
-  EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true));
-  EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false));
+  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
+  EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
+  EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
+  EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
+  EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
 }
 
 #endif  // defined(OS_WIN)
 
-class TaskThatPumps : public OrderedTasks {
- public:
-  TaskThatPumps(TaskList* order, int cookie)
-      : OrderedTasks(order, PUMPS, cookie) {
-  }
-
-  virtual void Run() {
-    RunStart();
-    bool old_state = MessageLoop::current()->NestableTasksAllowed();
-    MessageLoop::current()->SetNestableTasksAllowed(true);
-    MessageLoop::current()->RunAllPending();
-    MessageLoop::current()->SetNestableTasksAllowed(old_state);
-    RunEnd();
-  }
-};
+void FuncThatPumps(TaskList* order, int cookie) {
+  order->RecordStart(PUMPS, cookie);
+  bool old_state = MessageLoop::current()->NestableTasksAllowed();
+  MessageLoop::current()->SetNestableTasksAllowed(true);
+  MessageLoop::current()->RunAllPending();
+  MessageLoop::current()->SetNestableTasksAllowed(old_state);
+  order->RecordEnd(PUMPS, cookie);
+}
 
 // Tests that non nestable tasks run in FIFO if there are no nested loops.
-void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) {
+void RunTest_NonNestableWithNoNesting(
+    MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
   TaskList order;
 
-  Task* task = new OrderedTasks(&order, 1);
-  MessageLoop::current()->PostNonNestableTask(FROM_HERE, task);
-  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2));
-  MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3));
+  MessageLoop::current()->PostNonNestableTask(
+      FROM_HERE,
+      base::Bind(&OrderedFunc, &order, 1));
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&OrderedFunc, &order, 2));
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&QuitFunc, &order, 3));
   MessageLoop::current()->Run();
 
   // FIFO order.
-  ASSERT_EQ(6U, order.size());
-  EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false));
-  EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true));
-  EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false));
-  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
-  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
+  ASSERT_EQ(6U, order.Size());
+  EXPECT_EQ(order.Get(0), TaskItem(ORDERERD, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 1, false));
+  EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 2, true));
+  EXPECT_EQ(order.Get(3), TaskItem(ORDERERD, 2, false));
+  EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
+  EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
 }
 
 // Tests that non nestable tasks don't run when there's code in the call stack.
@@ -1113,42 +1044,52 @@
 
   TaskList order;
 
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new TaskThatPumps(&order, 1));
-  Task* task = new OrderedTasks(&order, 2);
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&FuncThatPumps, &order, 1));
   if (use_delayed) {
-    MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1);
+    MessageLoop::current()->PostNonNestableDelayedTask(
+        FROM_HERE,
+        base::Bind(&OrderedFunc, &order, 2),
+        1);
   } else {
-    MessageLoop::current()->PostNonNestableTask(FROM_HERE, task);
+    MessageLoop::current()->PostNonNestableTask(
+        FROM_HERE,
+        base::Bind(&OrderedFunc, &order, 2));
   }
-  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3));
-  MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50));
-  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5));
-  Task* non_nestable_quit = new QuitTask(&order, 6);
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&OrderedFunc, &order, 3));
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&SleepFunc, &order, 4, 50));
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   base::Bind(&OrderedFunc, &order, 5));
   if (use_delayed) {
-    MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE,
-                                                       non_nestable_quit,
-                                                       2);
+    MessageLoop::current()->PostNonNestableDelayedTask(
+        FROM_HERE,
+        base::Bind(&QuitFunc, &order, 6),
+        2);
   } else {
-    MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit);
+    MessageLoop::current()->PostNonNestableTask(
+        FROM_HERE,
+        base::Bind(&QuitFunc, &order, 6));
   }
 
   MessageLoop::current()->Run();
 
   // FIFO order.
-  ASSERT_EQ(12U, order.size());
-  EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true));
-  EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true));
-  EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false));
-  EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true));
-  EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false));
-  EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true));
-  EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false));
-  EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false));
-  EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true));
-  EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false));
-  EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true));
-  EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false));
+  ASSERT_EQ(12U, order.Size());
+  EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
+  EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 3, true));
+  EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 3, false));
+  EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
+  EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
+  EXPECT_EQ(order.Get(5), TaskItem(ORDERERD, 5, true));
+  EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 5, false));
+  EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
+  EXPECT_EQ(order.Get(8), TaskItem(ORDERERD, 2, true));
+  EXPECT_EQ(order.Get(9), TaskItem(ORDERERD, 2, false));
+  EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
+  EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
 }
 
 #if defined(OS_WIN)
@@ -1171,18 +1112,16 @@
   int dispatch_count_;
 };
 
+void MouseDownUp() {
+  PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
+  PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
+}
+
 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
-  class MyTask : public Task {
-  public:
-    virtual void Run() {
-      PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
-      PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
-    }
-  };
-  Task* task = new MyTask();
-  MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+                                          base::Bind(&MouseDownUp), 100);
   DispatcherImpl dispatcher;
   MessageLoopForUI::current()->Run(&dispatcher);
   ASSERT_EQ(2, dispatcher.dispatch_count_);
@@ -1200,15 +1139,8 @@
 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
   MessageLoop loop(message_loop_type);
 
-  class MyTask : public Task {
-  public:
-    virtual void Run() {
-      PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
-      PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
-    }
-  };
-  Task* task = new MyTask();
-  MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+                                          base::Bind(&MouseDownUp), 100);
   HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
                                     MsgFilterProc,
                                     NULL,
@@ -1271,17 +1203,6 @@
   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
 }
 
-class IOHandlerTask : public Task {
- public:
-  explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
-  virtual void Run() {
-    handler_->Init();
-  }
-
- private:
-  TestIOHandler* handler_;
-};
-
 void RunTest_IOHandler() {
   base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
   ASSERT_TRUE(callback_called.IsValid());
@@ -1300,8 +1221,8 @@
   ASSERT_TRUE(NULL != thread_loop);
 
   TestIOHandler handler(kPipeName, callback_called, false);
-  IOHandlerTask* task = new IOHandlerTask(&handler);
-  thread_loop->PostTask(FROM_HERE, task);
+  thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
+                                              base::Unretained(&handler)));
   Sleep(100);  // Make sure the thread runs and sleeps for lack of work.
 
   const char buffer[] = "Hello there!";
@@ -1341,11 +1262,12 @@
 
   TestIOHandler handler1(kPipeName1, callback1_called, false);
   TestIOHandler handler2(kPipeName2, callback2_called, true);
-  IOHandlerTask* task1 = new IOHandlerTask(&handler1);
-  IOHandlerTask* task2 = new IOHandlerTask(&handler2);
-  thread_loop->PostTask(FROM_HERE, task1);
+  thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
+                                              base::Unretained(&handler1)));
+  // TODO(ajwong): Do we really need such long Sleeps in ths function?
   Sleep(100);  // Make sure the thread runs and sleeps for lack of work.
-  thread_loop->PostTask(FROM_HERE, task2);
+  thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
+                                              base::Unretained(&handler2)));
   Sleep(100);
 
   // At this time handler1 is waiting to be called, and the thread is waiting
@@ -1376,6 +1298,12 @@
 // that message loops work properly in all configurations.  Of course, in some
 // cases, a unit test may only be for a particular type of loop.
 
+TEST(MessageLoopTest, PostLegacyTask) {
+  RunTest_PostLegacyTask(MessageLoop::TYPE_DEFAULT);
+  RunTest_PostLegacyTask(MessageLoop::TYPE_UI);
+  RunTest_PostLegacyTask(MessageLoop::TYPE_IO);
+}
+
 TEST(MessageLoopTest, PostTask) {
   RunTest_PostTask(MessageLoop::TYPE_DEFAULT);
   RunTest_PostTask(MessageLoop::TYPE_UI);
@@ -1433,19 +1361,19 @@
 // TODO(darin): MessageLoop does not support deleting all tasks in the
 // destructor.
 // Fails, http://crbug.com/50272.
-TEST(MessageLoopTest, FAILS_EnsureTaskDeletion) {
-  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT);
-  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI);
-  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO);
+TEST(MessageLoopTest, FAILS_EnsureDeletion) {
+  RunTest_EnsureDeletion(MessageLoop::TYPE_DEFAULT);
+  RunTest_EnsureDeletion(MessageLoop::TYPE_UI);
+  RunTest_EnsureDeletion(MessageLoop::TYPE_IO);
 }
 
 // TODO(darin): MessageLoop does not support deleting all tasks in the
 // destructor.
 // Fails, http://crbug.com/50272.
-TEST(MessageLoopTest, FAILS_EnsureTaskDeletion_Chain) {
-  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT);
-  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI);
-  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO);
+TEST(MessageLoopTest, FAILS_EnsureDeletion_Chain) {
+  RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_DEFAULT);
+  RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_UI);
+  RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_IO);
 }
 
 #if defined(OS_WIN)
@@ -1518,23 +1446,15 @@
   RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true);
 }
 
-class DummyTask : public Task {
- public:
-  explicit DummyTask(int num_tasks) : num_tasks_(num_tasks) {}
-
-  virtual void Run() {
-    if (num_tasks_ > 1) {
-      MessageLoop::current()->PostTask(
-          FROM_HERE,
-          new DummyTask(num_tasks_ - 1));
-    } else {
-      MessageLoop::current()->Quit();
-    }
+void PostNTasksThenQuit(int posts_remaining) {
+  if (posts_remaining > 1) {
+    MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&PostNTasksThenQuit, posts_remaining - 1));
+  } else {
+    MessageLoop::current()->Quit();
   }
-
- private:
-  const int num_tasks_;
-};
+}
 
 class DummyTaskObserver : public MessageLoop::TaskObserver {
  public:
@@ -1545,16 +1465,16 @@
 
   virtual ~DummyTaskObserver() {}
 
-  virtual void WillProcessTask(const Task* task) {
+  virtual void WillProcessTask(TimeTicks time_posted) OVERRIDE {
     num_tasks_started_++;
-    EXPECT_TRUE(task != NULL);
+    EXPECT_TRUE(time_posted != TimeTicks());
     EXPECT_LE(num_tasks_started_, num_tasks_);
     EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
   }
 
-  virtual void DidProcessTask(const Task* task) {
+  virtual void DidProcessTask(TimeTicks time_posted) OVERRIDE {
     num_tasks_processed_++;
-    EXPECT_TRUE(task != NULL);
+    EXPECT_TRUE(time_posted != TimeTicks());
     EXPECT_LE(num_tasks_started_, num_tasks_);
     EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
   }
@@ -1571,17 +1491,17 @@
 };
 
 TEST(MessageLoopTest, TaskObserver) {
-  const int kNumTasks = 6;
-  DummyTaskObserver observer(kNumTasks);
+  const int kNumPosts = 6;
+  DummyTaskObserver observer(kNumPosts);
 
   MessageLoop loop;
   loop.AddTaskObserver(&observer);
-  loop.PostTask(FROM_HERE, new DummyTask(kNumTasks));
+  loop.PostTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, kNumPosts));
   loop.Run();
   loop.RemoveTaskObserver(&observer);
 
-  EXPECT_EQ(kNumTasks, observer.num_tasks_started());
-  EXPECT_EQ(kNumTasks, observer.num_tasks_processed());
+  EXPECT_EQ(kNumPosts, observer.num_tasks_started());
+  EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
 }
 
 #if defined(OS_WIN)
@@ -1612,13 +1532,15 @@
   EXPECT_FALSE(loop.high_resolution_timers_enabled());
 
   // Post a fast task to enable the high resolution timers.
-  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs);
+  loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
+                       kFastTimerMs);
   loop.Run();
   EXPECT_TRUE(loop.high_resolution_timers_enabled());
 
   // Post a slow task and verify high resolution timers
   // are still enabled.
-  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
+  loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
+                       kSlowTimerMs);
   loop.Run();
   EXPECT_TRUE(loop.high_resolution_timers_enabled());
 
@@ -1626,7 +1548,8 @@
   Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs);
 
   // Post a slow task to disable the high resolution timers.
-  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
+  loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
+                       kSlowTimerMs);
   loop.Run();
   EXPECT_FALSE(loop.high_resolution_timers_enabled());
 }
@@ -1706,13 +1629,18 @@
 #endif  // defined(OS_POSIX) && !defined(OS_NACL)
 
 namespace {
-class RunAtDestructionTask : public Task {
+// Inject a test point for recording the destructor calls for Closure objects
+// send to MessageLoop::PostTask(). It is awkward usage since we are trying to
+// hook the actual destruction, which is not a common operation.
+class DestructionObserverProbe :
+  public base::RefCounted<DestructionObserverProbe> {
  public:
-  RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called)
+  DestructionObserverProbe(bool* task_destroyed,
+                           bool* destruction_observer_called)
       : task_destroyed_(task_destroyed),
         destruction_observer_called_(destruction_observer_called) {
   }
-  ~RunAtDestructionTask() {
+  virtual ~DestructionObserverProbe() {
     EXPECT_FALSE(*destruction_observer_called_);
     *task_destroyed_ = true;
   }
@@ -1760,7 +1688,9 @@
   loop->AddDestructionObserver(&observer);
   loop->PostDelayedTask(
       FROM_HERE,
-      new RunAtDestructionTask(&task_destroyed, &destruction_observer_called),
+      base::Bind(&DestructionObserverProbe::Run,
+                 new DestructionObserverProbe(&task_destroyed,
+                                              &destruction_observer_called)),
       kDelayMS);
   delete loop;
   EXPECT_TRUE(observer.task_destroyed_before_message_loop());