Adds the ability for MessageLoop to take a MessagePump

Using default args is against style guide, but there are a ton of
places (mostly tests) that define a MessageLoop as a member. I'll see
about a cleanup pass that removes the default args.

BUG=none
TEST=NONE
R=darin@chromium.org

Review URL: https://codereview.chromium.org/61643006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233800 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 9f0e4f712366b55628efeffca4e55438aef80691
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 7cd22a8..6d3d59c 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -144,14 +144,7 @@
 #endif  // OS_WIN
       message_histogram_(NULL),
       run_loop_(NULL) {
-  DCHECK(!current()) << "should only have one message loop per thread";
-  lazy_tls_ptr.Pointer()->Set(this);
-
-  incoming_task_queue_ = new internal::IncomingTaskQueue(this);
-  message_loop_proxy_ =
-      new internal::MessageLoopProxyImpl(incoming_task_queue_);
-  thread_task_runner_handle_.reset(
-      new ThreadTaskRunnerHandle(message_loop_proxy_));
+  Init();
 
 // TODO(rvargas): Get rid of the OS guards.
 #if defined(OS_WIN)
@@ -198,6 +191,20 @@
   }
 }
 
+MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump)
+    : pump_(pump.Pass()),
+      type_(TYPE_CUSTOM),
+      exception_restoration_(false),
+      nestable_tasks_allowed_(true),
+#if defined(OS_WIN)
+      os_modal_loop_(false),
+#endif  // OS_WIN
+      message_histogram_(NULL),
+      run_loop_(NULL) {
+  DCHECK(pump_.get());
+  Init();
+}
+
 MessageLoop::~MessageLoop() {
   DCHECK_EQ(this, current());
 
@@ -397,6 +404,17 @@
 
 //------------------------------------------------------------------------------
 
+void MessageLoop::Init() {
+  DCHECK(!current()) << "should only have one message loop per thread";
+  lazy_tls_ptr.Pointer()->Set(this);
+
+  incoming_task_queue_ = new internal::IncomingTaskQueue(this);
+  message_loop_proxy_ =
+      new internal::MessageLoopProxyImpl(incoming_task_queue_);
+  thread_task_runner_handle_.reset(
+      new ThreadTaskRunnerHandle(message_loop_proxy_));
+}
+
 // Runs the loop in two different SEH modes:
 // enable_SEH_restoration_ = false : any unhandled exception goes to the last
 // one that calls SetUnhandledExceptionFilter().
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 0eb1803..84e1449 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -128,9 +128,13 @@
   //   TYPE_JAVA behaves in essence like TYPE_UI, except during construction
   //   where it does not use the main thread specific pump factory.
   //
+  // TYPE_CUSTOM
+  //   MessagePump was supplied to constructor.
+  //
   enum Type {
     TYPE_DEFAULT,
     TYPE_UI,
+    TYPE_CUSTOM,
 #if defined(TOOLKIT_GTK)
     TYPE_GPU,
 #endif
@@ -143,6 +147,9 @@
   // Normally, it is not necessary to instantiate a MessageLoop.  Instead, it
   // is typical to make use of the current thread's MessageLoop instance.
   explicit MessageLoop(Type type = TYPE_DEFAULT);
+  // Creates a TYPE_CUSTOM MessageLoop with the supplied MessagePump, which must
+  // be non-NULL.
+  explicit MessageLoop(scoped_ptr<base::MessagePump> pump);
   virtual ~MessageLoop();
 
   // Returns the MessageLoop object for the current thread, or null if none.
@@ -442,6 +449,9 @@
   friend class internal::IncomingTaskQueue;
   friend class RunLoop;
 
+  // Configures various members for the two constructors.
+  void Init();
+
   // A function to encapsulate all the exception handling capability in the
   // stacks around the running of a main message loop.  It will run the message
   // loop in a SEH try block or not depending on the set_SEH_restoration()
@@ -504,7 +514,7 @@
   virtual void GetQueueingInformation(size_t* queue_size,
                                       TimeDelta* queueing_delay) OVERRIDE;
 
-  Type type_;
+  const Type type_;
 
   // A list of tasks that need to be processed by this instance.  Note that
   // this queue is only accessed (push/pop) by our current thread.
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index aca4ddb..ae4d373 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -49,6 +49,20 @@
         event(false, false) {}
 };
 
+Thread::Options::Options()
+    : message_loop_type(MessageLoop::TYPE_DEFAULT),
+      stack_size(0) {
+}
+
+Thread::Options::Options(MessageLoop::Type type,
+                         size_t size)
+    : message_loop_type(type),
+      stack_size(size) {
+}
+
+Thread::Options::~Options() {
+}
+
 Thread::Thread(const char* name)
     :
 #if defined(OS_WIN)
@@ -174,8 +188,14 @@
   {
     // The message loop for this thread.
     // Allocated on the heap to centralize any leak reports at this line.
-    scoped_ptr<MessageLoop> message_loop(
-        new MessageLoop(startup_data_->options.message_loop_type));
+    scoped_ptr<MessageLoop> message_loop;
+    if (!startup_data_->options.message_pump_factory.is_null()) {
+      message_loop.reset(
+          new MessageLoop(startup_data_->options.message_pump_factory.Run()));
+    } else {
+      message_loop.reset(
+          new MessageLoop(startup_data_->options.message_loop_type));
+    }
 
     // Complete the initialization of our Thread object.
     thread_id_ = PlatformThread::CurrentId();
diff --git a/base/threading/thread.h b/base/threading/thread.h
index 98831b8..99f9dd4 100644
--- a/base/threading/thread.h
+++ b/base/threading/thread.h
@@ -8,12 +8,16 @@
 #include <string>
 
 #include "base/base_export.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/threading/platform_thread.h"
 
 namespace base {
 
+class MessagePump;
+
 // A simple thread abstraction that establishes a MessageLoop on a new thread.
 // The consumer uses the MessageLoop of the thread to cause code to execute on
 // the thread.  When this object is destroyed the thread is terminated.  All
@@ -29,14 +33,23 @@
 //  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
 class BASE_EXPORT Thread : PlatformThread::Delegate {
  public:
-  struct Options {
-    Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
-    Options(MessageLoop::Type type, size_t size)
-        : message_loop_type(type), stack_size(size) {}
+  struct BASE_EXPORT Options {
+    typedef Callback<scoped_ptr<MessagePump>()> MessagePumpFactory;
+
+    Options();
+    Options(MessageLoop::Type type, size_t size);
+    ~Options();
 
     // Specifies the type of message loop that will be allocated on the thread.
+    // This is ignored if message_pump_factory.is_null() is false.
     MessageLoop::Type message_loop_type;
 
+    // Used to create the MessagePump for the MessageLoop. The callback is Run()
+    // on the thread. If message_pump_factory.is_null(), then a MessagePump
+    // appropriate for |message_loop_type| is created. Setting this forces the
+    // MessageLoop::Type to TYPE_CUSTOM.
+    MessagePumpFactory message_pump_factory;
+
     // Specifies the maximum stack size that the thread is allowed to use.
     // This does not necessarily correspond to the thread's initial stack size.
     // A value of 0 indicates that the default maximum should be used.