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


CrOS-Libchrome-Original-Commit: b224f79da757434cee55b721806ff8553fc80b0a
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index 3293dbb..27434e0 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -145,7 +145,7 @@
 #pragma warning(default:4624)
 #endif
 
-  template <void(BaseMixin::*)(void)>  struct Helper {};
+  template <void(BaseMixin::*)(void)> struct Helper {};
 
   template <typename C>
   static No& Check(Helper<&C::AddRef>*, Helper<&C::Release>*);
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 1154c3e..bf0d25d 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -4,20 +4,18 @@
 
 #include "base/message_loop.h"
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#endif
-
 #include <algorithm>
 
+#include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/message_pump_default.h"
 #include "base/metrics/histogram.h"
+#include "base/scoped_ptr.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread_local.h"
+#include "base/tracked_objects.h"
 
 #if defined(OS_MACOSX)
 #include "base/message_pump_mac.h"
@@ -26,6 +24,8 @@
 #include "base/message_pump_libevent.h"
 #endif
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
 #include "base/message_pump_glib.h"
 #endif
 #if defined(TOUCH_UI)
@@ -81,6 +81,40 @@
 
 bool enable_histogrammer_ = false;
 
+// TODO(ajwong): This is one use case for having a Owned() tag that behaves
+// like a "Unique" pointer.  If we had that, and Tasks were always safe to
+// delete on MessageLoop shutdown, this class could just be a function.
+class TaskClosureAdapter : public base::RefCounted<TaskClosureAdapter> {
+ public:
+  // |should_leak_task| points to a flag variable that can be used to determine
+  // if this class should leak the Task on destruction.  This is important
+  // at MessageLoop shutdown since not all tasks can be safely deleted without
+  // running.  See MessageLoop::DeletePendingTasks() for the exact behavior
+  // of when a Task should be deleted. It is subtle.
+  TaskClosureAdapter(Task* task, bool* should_leak_task)
+      : task_(task),
+        should_leak_task_(should_leak_task) {
+  }
+
+  void Run() {
+    task_->Run();
+    delete task_;
+    task_ = NULL;
+  }
+
+ private:
+  friend class base::RefCounted<TaskClosureAdapter>;
+
+  ~TaskClosureAdapter() {
+    if (!*should_leak_task_) {
+      delete task_;
+    }
+  }
+
+  Task* task_;
+  bool* should_leak_task_;
+};
+
 }  // namespace
 
 //------------------------------------------------------------------------------
@@ -124,6 +158,7 @@
       exception_restoration_(false),
       message_histogram_(NULL),
       state_(NULL),
+      should_leak_tasks_(true),
 #ifdef OS_WIN
       os_modal_loop_(false),
 #endif  // OS_WIN
@@ -220,22 +255,74 @@
 
 void MessageLoop::PostTask(
     const tracked_objects::Location& from_here, Task* task) {
-  PostTask_Helper(from_here, task, 0, true);
+  PendingTask pending_task(
+      base::Bind(&TaskClosureAdapter::Run,
+                 new TaskClosureAdapter(task, &should_leak_tasks_)),
+      from_here,
+      CalculateDelayedRuntime(0), true);
+  AddToIncomingQueue(&pending_task);
 }
 
 void MessageLoop::PostDelayedTask(
     const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
-  PostTask_Helper(from_here, task, delay_ms, true);
+  PendingTask pending_task(
+      base::Bind(&TaskClosureAdapter::Run,
+                 new TaskClosureAdapter(task, &should_leak_tasks_)),
+      from_here,
+      CalculateDelayedRuntime(delay_ms), true);
+  AddToIncomingQueue(&pending_task);
 }
 
 void MessageLoop::PostNonNestableTask(
     const tracked_objects::Location& from_here, Task* task) {
-  PostTask_Helper(from_here, task, 0, false);
+  PendingTask pending_task(
+      base::Bind(&TaskClosureAdapter::Run,
+                 new TaskClosureAdapter(task, &should_leak_tasks_)),
+      from_here,
+      CalculateDelayedRuntime(0), false);
+  AddToIncomingQueue(&pending_task);
 }
 
 void MessageLoop::PostNonNestableDelayedTask(
     const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
-  PostTask_Helper(from_here, task, delay_ms, false);
+  PendingTask pending_task(
+      base::Bind(&TaskClosureAdapter::Run,
+                 new TaskClosureAdapter(task, &should_leak_tasks_)),
+      from_here,
+      CalculateDelayedRuntime(delay_ms), false);
+  AddToIncomingQueue(&pending_task);
+}
+
+void MessageLoop::PostTask(
+    const tracked_objects::Location& from_here, const base::Closure& task) {
+  DCHECK(!task.is_null());
+  PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), true);
+  AddToIncomingQueue(&pending_task);
+}
+
+void MessageLoop::PostDelayedTask(
+    const tracked_objects::Location& from_here, const base::Closure& task,
+    int64 delay_ms) {
+  DCHECK(!task.is_null());
+  PendingTask pending_task(task, from_here,
+                           CalculateDelayedRuntime(delay_ms), true);
+  AddToIncomingQueue(&pending_task);
+}
+
+void MessageLoop::PostNonNestableTask(
+    const tracked_objects::Location& from_here, const base::Closure& task) {
+  DCHECK(!task.is_null());
+  PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), false);
+  AddToIncomingQueue(&pending_task);
+}
+
+void MessageLoop::PostNonNestableDelayedTask(
+    const tracked_objects::Location& from_here, const base::Closure& task,
+    int64 delay_ms) {
+  DCHECK(!task.is_null());
+  PendingTask pending_task(task, from_here,
+                           CalculateDelayedRuntime(delay_ms), false);
+  AddToIncomingQueue(&pending_task);
 }
 
 void MessageLoop::Run() {
@@ -353,31 +440,40 @@
   if (deferred_non_nestable_work_queue_.empty())
     return false;
 
-  Task* task = deferred_non_nestable_work_queue_.front().task;
+  PendingTask pending_task = deferred_non_nestable_work_queue_.front();
   deferred_non_nestable_work_queue_.pop();
 
-  RunTask(task);
+  RunTask(pending_task);
   return true;
 }
 
-void MessageLoop::RunTask(Task* task) {
+void MessageLoop::RunTask(const PendingTask& pending_task) {
   DCHECK(nestable_tasks_allowed_);
   // Execute the task and assume the worst: It is probably not reentrant.
   nestable_tasks_allowed_ = false;
 
   HistogramEvent(kTaskRunEvent);
   FOR_EACH_OBSERVER(TaskObserver, task_observers_,
-                    WillProcessTask(task));
-  task->Run();
-  FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(task));
-  delete task;
+                    WillProcessTask(pending_task.time_posted));
+  pending_task.task.Run();
+  FOR_EACH_OBSERVER(TaskObserver, task_observers_,
+                    DidProcessTask(pending_task.time_posted));
+
+#if defined(TRACK_ALL_TASK_OBJECTS)
+  if (tracked_objects::ThreadData::IsActive() && pending_task.post_births) {
+    tracked_objects::ThreadData::current()->TallyADeath(
+        *pending_task.post_births,
+        TimeTicks::Now() - pending_task.time_posted);
+  }
+#endif  // defined(TRACK_ALL_TASK_OBJECTS)
 
   nestable_tasks_allowed_ = true;
 }
 
-bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
+bool MessageLoop::DeferOrRunPendingTask(
+    const PendingTask& pending_task) {
   if (pending_task.nestable || state_->run_depth == 1) {
-    RunTask(pending_task.task);
+    RunTask(pending_task);
     // Show that we ran a task (Note: a new one might arrive as a
     // consequence!).
     return true;
@@ -419,6 +515,18 @@
 
 bool MessageLoop::DeletePendingTasks() {
   bool did_work = !work_queue_.empty();
+  // TODO(darin): Delete all tasks once it is safe to do so.
+  // Until it is totally safe, just do it when running Purify or
+  // Valgrind.
+  //
+  // See http://crbug.com/61131
+  //
+#if defined(PURIFY) || defined(USE_HEAPCHECKER)
+  should_leak_tasks_ = false;
+#else
+      if (RunningOnValgrind())
+        should_leak_tasks_ = false;
+#endif  // defined(OS_POSIX)
   while (!work_queue_.empty()) {
     PendingTask pending_task = work_queue_.front();
     work_queue_.pop();
@@ -427,52 +535,31 @@
       // normally be deleted in case of any funny dependencies between delayed
       // tasks.
       AddToDelayedWorkQueue(pending_task);
-    } else {
-      // TODO(darin): Delete all tasks once it is safe to do so.
-      // Until it is totally safe, just do it when running Purify or
-      // Valgrind.
-#if defined(PURIFY) || defined(USE_HEAPCHECKER)
-      delete pending_task.task;
-#else
-      if (RunningOnValgrind())
-        delete pending_task.task;
-#endif  // defined(OS_POSIX)
     }
   }
   did_work |= !deferred_non_nestable_work_queue_.empty();
   while (!deferred_non_nestable_work_queue_.empty()) {
-    // TODO(darin): Delete all tasks once it is safe to do so.
-    // Until it is totaly safe, only delete them under Purify and Valgrind.
-    Task* task = NULL;
-#if defined(PURIFY) || defined(USE_HEAPCHECKER)
-    task = deferred_non_nestable_work_queue_.front().task;
-#else
-    if (RunningOnValgrind())
-      task = deferred_non_nestable_work_queue_.front().task;
-#endif
     deferred_non_nestable_work_queue_.pop();
-    if (task)
-      delete task;
   }
   did_work |= !delayed_work_queue_.empty();
+
+  // Historically, we always delete the task regardless of valgrind status. It's
+  // not completely clear why we want to leak them in the loops above.  This
+  // code is replicating legacy behavior, and should not be considered
+  // absolutely "correct" behavior.  See TODO above about deleting all tasks
+  // when it's safe.
+  should_leak_tasks_ = false;
   while (!delayed_work_queue_.empty()) {
-    Task* task = delayed_work_queue_.top().task;
     delayed_work_queue_.pop();
-    delete task;
   }
+  should_leak_tasks_ = true;
   return did_work;
 }
 
-// Possibly called on a background thread!
-void MessageLoop::PostTask_Helper(
-    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
-    bool nestable) {
-  task->SetBirthPlace(from_here);
-
-  PendingTask pending_task(task, nestable);
-
+TimeTicks MessageLoop::CalculateDelayedRuntime(int64 delay_ms) {
+  TimeTicks delayed_run_time;
   if (delay_ms > 0) {
-    pending_task.delayed_run_time =
+    delayed_run_time =
         TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms);
 
 #if defined(OS_WIN)
@@ -504,6 +591,11 @@
   }
 #endif
 
+  return delayed_run_time;
+}
+
+// Possibly called on a background thread!
+void MessageLoop::AddToIncomingQueue(PendingTask* pending_task) {
   // Warning: Don't try to short-circuit, and handle this thread's tasks more
   // directly, as it could starve handling of foreign threads.  Put every task
   // into this queue.
@@ -513,7 +605,8 @@
     base::AutoLock locked(incoming_queue_lock_);
 
     bool was_empty = incoming_queue_.empty();
-    incoming_queue_.push(pending_task);
+    incoming_queue_.push(*pending_task);
+    pending_task->task.Reset();
     if (!was_empty)
       return;  // Someone else should have started the sub-pump.
 
@@ -566,8 +659,8 @@
       work_queue_.pop();
       if (!pending_task.delayed_run_time.is_null()) {
         AddToDelayedWorkQueue(pending_task);
-        // If we changed the topmost task, then it is time to re-schedule.
-        if (delayed_work_queue_.top().task == pending_task.task)
+        // If we changed the topmost task, then it is time to reschedule.
+        if (delayed_work_queue_.top().task.Equals(pending_task.task))
           pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
       } else {
         if (DeferOrRunPendingTask(pending_task))
@@ -580,7 +673,7 @@
   return false;
 }
 
-bool MessageLoop::DoDelayedWork(base::TimeTicks* next_delayed_work_time) {
+bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
   if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
     recent_time_ = *next_delayed_work_time = TimeTicks();
     return false;
@@ -648,6 +741,33 @@
 //------------------------------------------------------------------------------
 // MessageLoop::PendingTask
 
+MessageLoop::PendingTask::PendingTask(
+    const base::Closure& task,
+    const tracked_objects::Location& posted_from,
+    TimeTicks delayed_run_time,
+    bool nestable)
+    : task(task),
+      time_posted(TimeTicks::Now()),
+      delayed_run_time(delayed_run_time),
+      sequence_num(0),
+      nestable(nestable) {
+#if defined(TRACK_ALL_TASK_OBJECTS)
+  if (tracked_objects::ThreadData::IsActive()) {
+    tracked_objects::ThreadData* current_thread_data =
+        tracked_objects::ThreadData::current();
+    if (current_thread_data) {
+      post_births = current_thread_data->TallyABirth(posted_from);
+    } else {
+      // Shutdown started, and this thread wasn't registered.
+      post_births = NULL;
+    }
+  }
+#endif  // defined(TRACK_ALL_TASK_OBJECTS)
+}
+
+MessageLoop::PendingTask::~PendingTask() {
+}
+
 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
   // Since the top of a priority queue is defined as the "greatest" element, we
   // need to invert the comparison here.  We want the smaller time to be at the
diff --git a/base/message_loop.h b/base/message_loop.h
index 519e4a3..b601d9e 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -11,11 +11,14 @@
 
 #include "base/base_api.h"
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_pump.h"
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
 #include "base/task.h"
+#include "base/time.h"
+#include "base/tracked.h"
 
 #if defined(OS_WIN)
 // We need this to declare base::MessagePumpWin::Dispatcher, which we should
@@ -36,6 +39,12 @@
 class Histogram;
 }
 
+#if defined(TRACK_ALL_TASK_OBJECTS)
+namespace tracked_objects {
+class Births;
+}
+#endif  // defined(TRACK_ALL_TASK_OBJECTS)
+
 // A MessageLoop is used to process events for a particular thread.  There is
 // at most one MessageLoop instance per thread.
 //
@@ -163,6 +172,29 @@
   void PostNonNestableDelayedTask(
       const tracked_objects::Location& from_here, Task* task, int64 delay_ms);
 
+  // TODO(ajwong): Remove the functions above once the Task -> Closure migration
+  // is complete.
+  //
+  // There are 2 sets of Post*Task functions, one which takes the older Task*
+  // function object representation, and one that takes the newer base::Closure.
+  // We have this overload to allow a staged transition between the two systems.
+  // Once the transition is done, the functions above should be deleted.
+  void PostTask(
+      const tracked_objects::Location& from_here,
+      const base::Closure& task);
+
+  void PostDelayedTask(
+      const tracked_objects::Location& from_here,
+      const base::Closure& task, int64 delay_ms);
+
+  void PostNonNestableTask(
+      const tracked_objects::Location& from_here,
+      const base::Closure& task);
+
+  void PostNonNestableDelayedTask(
+      const tracked_objects::Location& from_here,
+      const base::Closure& task, int64 delay_ms);
+
   // A variant on PostTask that deletes the given object.  This is useful
   // if the object needs to live until the next run of the MessageLoop (for
   // example, deleting a RenderProcessHost from within an IPC callback is not
@@ -289,10 +321,10 @@
     TaskObserver();
 
     // This method is called before processing a task.
-    virtual void WillProcessTask(const Task* task) = 0;
+    virtual void WillProcessTask(base::TimeTicks time_posted) = 0;
 
     // This method is called after processing a task.
-    virtual void DidProcessTask(const Task* task) = 0;
+    virtual void DidProcessTask(base::TimeTicks time_posted) = 0;
 
    protected:
     virtual ~TaskObserver();
@@ -356,17 +388,34 @@
 
   // This structure is copied around by value.
   struct PendingTask {
-    PendingTask(Task* task, bool nestable)
-        : task(task), sequence_num(0), nestable(nestable) {
-    }
+    PendingTask(const base::Closure& task,
+                const tracked_objects::Location& posted_from,
+                base::TimeTicks delayed_run_time,
+                bool nestable);
+    ~PendingTask();
 
     // Used to support sorting.
     bool operator<(const PendingTask& other) const;
 
-    Task* task;                        // The task to run.
-    base::TimeTicks delayed_run_time;  // The time when the task should be run.
-    int sequence_num;                  // Secondary sort key for run time.
-    bool nestable;                     // OK to dispatch from a nested loop.
+    // The task to run.
+    base::Closure task;
+
+#if defined(TRACK_ALL_TASK_OBJECTS)
+    // Counter for location where the Closure was posted from.
+    tracked_objects::Births* post_births;
+#endif  // defined(TRACK_ALL_TASK_OBJECTS)
+
+    // Time this PendingTask was posted.
+    base::TimeTicks time_posted;
+
+    // The time when the task should be run.
+    base::TimeTicks delayed_run_time;
+
+    // Secondary sort key for run time.
+    int sequence_num;
+
+    // OK to dispatch from a nested loop.
+    bool nestable;
   };
 
   class TaskQueue : public std::queue<PendingTask> {
@@ -406,8 +455,8 @@
   // Called to process any delayed non-nestable tasks.
   bool ProcessNextDelayedNonNestableTask();
 
-  // Runs the specified task and deletes it.
-  void RunTask(Task* task);
+  // Runs the specified PendingTask.
+  void RunTask(const PendingTask& pending_task);
 
   // Calls RunTask or queues the pending_task on the deferred task list if it
   // cannot be run right now.  Returns true if the task was run.
@@ -416,6 +465,14 @@
   // Adds the pending task to delayed_work_queue_.
   void AddToDelayedWorkQueue(const PendingTask& pending_task);
 
+  // Adds the pending task to our incoming_queue_.
+  //
+  // Caller retains ownership of |pending_task|, but this function will
+  // reset the value of pending_task->task.  This is needed to ensure
+  // that the posting call stack does not retain pending_task->task
+  // beyond this function call.
+  void AddToIncomingQueue(PendingTask* pending_task);
+
   // Load tasks from the incoming_queue_ into work_queue_ if the latter is
   // empty.  The former requires a lock to access, while the latter is directly
   // accessible on this thread.
@@ -426,9 +483,8 @@
   // true if some work was done.
   bool DeletePendingTasks();
 
-  // Post a task to our incomming queue.
-  void PostTask_Helper(const tracked_objects::Location& from_here, Task* task,
-                       int64 delay_ms, bool nestable);
+  // Calcuates the time at which a PendingTask should run.
+  base::TimeTicks CalculateDelayedRuntime(int64 delay_ms);
 
   // Start recording histogram info about events and action IF it was enabled
   // and IF the statistics recorder can accept a registration of our histogram.
@@ -477,14 +533,18 @@
 
   // A null terminated list which creates an incoming_queue of tasks that are
   // acquired under a mutex for processing on this instance's thread. These
-  // tasks have not yet been sorted out into items for our work_queue_ vs
-  // items that will be handled by the TimerManager.
+  // tasks have not yet been sorted out into items for our work_queue_ vs items
+  // that will be handled by the TimerManager.
   TaskQueue incoming_queue_;
   // Protect access to incoming_queue_.
   mutable base::Lock incoming_queue_lock_;
 
   RunState* state_;
 
+  // The need for this variable is subtle. Please see implementation comments
+  // around where it is used.
+  bool should_leak_tasks_;
+
 #if defined(OS_WIN)
   base::TimeTicks high_resolution_timer_expiration_;
   // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index cd681f3..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());