Move message_pump to base/message_loop.

This also fixes some namespace usage inside the message pump files and updates all users of these files to use the new location.

Reland of 206507.
Original review https://codereview.chromium.org/17078005/
TBR=sky

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

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


CrOS-Libchrome-Original-Commit: 59e69e745ba3fa290ff3c50e65c3db03ee9dde6b
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 0364a52..4e0c5f6 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -14,7 +14,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop_proxy_impl.h"
-#include "base/message_pump_default.h"
+#include "base/message_loop/message_pump_default.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/run_loop.h"
@@ -25,13 +25,13 @@
 #include "base/tracked_objects.h"
 
 #if defined(OS_MACOSX)
-#include "base/message_pump_mac.h"
+#include "base/message_loop/message_pump_mac.h"
 #endif
 #if defined(OS_POSIX) && !defined(OS_IOS)
-#include "base/message_pump_libevent.h"
+#include "base/message_loop/message_pump_libevent.h"
 #endif
 #if defined(OS_ANDROID)
-#include "base/message_pump_android.h"
+#include "base/message_loop/message_pump_android.h"
 #endif
 
 #if defined(TOOLKIT_GTK)
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index d26b673..e765cef 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -14,7 +14,7 @@
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop_proxy.h"
-#include "base/message_pump.h"
+#include "base/message_loop/message_pump.h"
 #include "base/observer_list.h"
 #include "base/pending_task.h"
 #include "base/sequenced_task_runner_helpers.h"
@@ -25,25 +25,26 @@
 #if defined(OS_WIN)
 // We need this to declare base::MessagePumpWin::Dispatcher, which we should
 // really just eliminate.
-#include "base/message_pump_win.h"
+#include "base/message_loop/message_pump_win.h"
 #elif defined(OS_IOS)
-#include "base/message_pump_io_ios.h"
+#include "base/message_loop/message_pump_io_ios.h"
 #elif defined(OS_POSIX)
-#include "base/message_pump_libevent.h"
+#include "base/message_loop/message_pump_libevent.h"
 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
 
 #if defined(USE_AURA) && defined(USE_X11) && !defined(OS_NACL)
-#include "base/message_pump_aurax11.h"
+#include "base/message_loop/message_pump_aurax11.h"
 #elif defined(USE_OZONE) && !defined(OS_NACL)
-#include "base/message_pump_ozone.h"
+#include "base/message_loop/message_pump_ozone.h"
 #else
-#include "base/message_pump_gtk.h"
+#include "base/message_loop/message_pump_gtk.h"
 #endif
 
 #endif
 #endif
 
 namespace base {
+
 class HistogramBase;
 class MessageLoopLockTest;
 class RunLoop;
@@ -83,12 +84,12 @@
 // Please be SURE your task is reentrant (nestable) and all global variables
 // are stable and accessible before calling SetNestableTasksAllowed(true).
 //
-class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
+class BASE_EXPORT MessageLoop : public MessagePump::Delegate {
  public:
 
 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-  typedef base::MessagePumpDispatcher Dispatcher;
-  typedef base::MessagePumpObserver Observer;
+  typedef MessagePumpDispatcher Dispatcher;
+  typedef MessagePumpObserver Observer;
 #endif
 
   // A MessageLoop has a particular type, which indicates the set of
@@ -121,7 +122,7 @@
 
   static void EnableHistogrammer(bool enable_histogrammer);
 
-  typedef base::MessagePump* (MessagePumpFactory)();
+  typedef MessagePump* (MessagePumpFactory)();
   // Uses the given base::MessagePumpForUIFactory to override the default
   // MessagePump implementation for 'TYPE_UI'. Returns true if the factory
   // was successfully registered.
@@ -174,27 +175,22 @@
   //
   // NOTE: These methods may be called on any thread.  The Task will be invoked
   // on the thread that executes MessageLoop::Run().
-  void PostTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task);
+  void PostTask(const tracked_objects::Location& from_here,
+                const Closure& task);
 
-  bool TryPostTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task);
+  bool TryPostTask(const tracked_objects::Location& from_here,
+                   const Closure& task);
 
-  void PostDelayedTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task,
-      base::TimeDelta delay);
+  void PostDelayedTask(const tracked_objects::Location& from_here,
+                       const Closure& task,
+                       TimeDelta delay);
 
-  void PostNonNestableTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task);
+  void PostNonNestableTask(const tracked_objects::Location& from_here,
+                           const Closure& task);
 
-  void PostNonNestableDelayedTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task,
-      base::TimeDelta delay);
+  void PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+                                  const Closure& task,
+                                  TimeDelta delay);
 
   // 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
@@ -264,12 +260,12 @@
   void QuitNow();
 
   // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdleClosure().
-  static base::Closure QuitClosure() { return QuitWhenIdleClosure(); }
+  static Closure QuitClosure() { return QuitWhenIdleClosure(); }
 
   // Deprecated: use RunLoop instead.
   // Construct a Closure that will call QuitWhenIdle(). Useful to schedule an
   // arbitrary MessageLoop to QuitWhenIdle.
-  static base::Closure QuitWhenIdleClosure();
+  static Closure QuitWhenIdleClosure();
 
   // Returns true if this loop is |type|. This allows subclasses (especially
   // those in tests) to specialize how they are identified.
@@ -286,7 +282,7 @@
   const std::string& thread_name() const { return thread_name_; }
 
   // Gets the message loop proxy associated with this message loop.
-  scoped_refptr<base::MessageLoopProxy> message_loop_proxy() {
+  scoped_refptr<MessageLoopProxy> message_loop_proxy() {
     return message_loop_proxy_.get();
   }
 
@@ -349,10 +345,10 @@
     TaskObserver();
 
     // This method is called before processing a task.
-    virtual void WillProcessTask(const base::PendingTask& pending_task) = 0;
+    virtual void WillProcessTask(const PendingTask& pending_task) = 0;
 
     // This method is called after processing a task.
-    virtual void DidProcessTask(const base::PendingTask& pending_task) = 0;
+    virtual void DidProcessTask(const PendingTask& pending_task) = 0;
 
    protected:
     virtual ~TaskObserver();
@@ -397,20 +393,20 @@
  protected:
 
 #if defined(OS_WIN)
-  base::MessagePumpWin* pump_win() {
-    return static_cast<base::MessagePumpWin*>(pump_.get());
+  MessagePumpWin* pump_win() {
+    return static_cast<MessagePumpWin*>(pump_.get());
   }
 #elif defined(OS_POSIX) && !defined(OS_IOS)
-  base::MessagePumpLibevent* pump_libevent() {
-    return static_cast<base::MessagePumpLibevent*>(pump_.get());
+  MessagePumpLibevent* pump_libevent() {
+    return static_cast<MessagePumpLibevent*>(pump_.get());
   }
 #endif
 
-  scoped_refptr<base::MessagePump> pump_;
+  scoped_refptr<MessagePump> pump_;
 
  private:
-  friend class base::RunLoop;
-  friend class base::MessageLoopLockTest;
+  friend class RunLoop;
+  friend class MessageLoopLockTest;
 
   // 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
@@ -431,14 +427,14 @@
   bool ProcessNextDelayedNonNestableTask();
 
   // Runs the specified PendingTask.
-  void RunTask(const base::PendingTask& pending_task);
+  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.
-  bool DeferOrRunPendingTask(const base::PendingTask& pending_task);
+  bool DeferOrRunPendingTask(const PendingTask& pending_task);
 
   // Adds the pending task to delayed_work_queue_.
-  void AddToDelayedWorkQueue(const base::PendingTask& pending_task);
+  void AddToDelayedWorkQueue(const PendingTask& pending_task);
 
   // This function attempts to add pending task to our incoming_queue_.
   // The append can only possibly fail when |use_try_lock| is true.
@@ -454,7 +450,7 @@
   // 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.
-  bool AddToIncomingQueue(base::PendingTask* pending_task, bool use_try_lock);
+  bool AddToIncomingQueue(PendingTask* pending_task, bool use_try_lock);
 
   // 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
@@ -467,7 +463,7 @@
   bool DeletePendingTasks();
 
   // Calculates the time at which a PendingTask should run.
-  base::TimeTicks CalculateDelayedRuntime(base::TimeDelta delay);
+  TimeTicks CalculateDelayedRuntime(TimeDelta delay);
 
   // Start recording histogram info about events and action IF it was enabled
   // and IF the statistics recorder can accept a registration of our histogram.
@@ -478,27 +474,27 @@
   // If message_histogram_ is NULL, this is a no-op.
   void HistogramEvent(int event);
 
-  // base::MessagePump::Delegate methods:
+  // MessagePump::Delegate methods:
   virtual bool DoWork() OVERRIDE;
-  virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time) OVERRIDE;
+  virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE;
   virtual bool DoIdleWork() OVERRIDE;
 
   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.
-  base::TaskQueue work_queue_;
+  TaskQueue work_queue_;
 
   // Contains delayed tasks, sorted by their 'delayed_run_time' property.
-  base::DelayedTaskQueue delayed_work_queue_;
+  DelayedTaskQueue delayed_work_queue_;
 
   // A recent snapshot of Time::Now(), used to check delayed_work_queue_.
-  base::TimeTicks recent_time_;
+  TimeTicks recent_time_;
 
   // A queue of non-nestable tasks that we had to defer because when it came
   // time to execute them we were in a nested message loop.  They will execute
   // once we're out of nested message loops.
-  base::TaskQueue deferred_non_nestable_work_queue_;
+  TaskQueue deferred_non_nestable_work_queue_;
 
   ObserverList<DestructionObserver> destruction_observers_;
 
@@ -510,19 +506,19 @@
 
   std::string thread_name_;
   // A profiling histogram showing the counts of various messages and events.
-  base::HistogramBase* message_histogram_;
+  HistogramBase* message_histogram_;
 
   // 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 delayed_work_queue_.
-  base::TaskQueue incoming_queue_;
+  TaskQueue incoming_queue_;
   // Protect access to incoming_queue_.
-  mutable base::Lock incoming_queue_lock_;
+  mutable Lock incoming_queue_lock_;
 
-  base::RunLoop* run_loop_;
+  RunLoop* run_loop_;
 
 #if defined(OS_WIN)
-  base::TimeTicks high_resolution_timer_expiration_;
+  TimeTicks high_resolution_timer_expiration_;
   // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
   // which enter a modal message loop.
   bool os_modal_loop_;
@@ -535,8 +531,8 @@
   ObserverList<TaskObserver> task_observers_;
 
   // The message loop proxy associated with this message loop, if one exists.
-  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
-  scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
+  scoped_refptr<MessageLoopProxy> message_loop_proxy_;
+  scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
 
   template <class T, class R> friend class base::subtle::DeleteHelperInternal;
   template <class T, class R> friend class base::subtle::ReleaseHelperInternal;
@@ -561,7 +557,7 @@
 class BASE_EXPORT MessageLoopForUI : public MessageLoop {
  public:
 #if defined(OS_WIN)
-  typedef base::MessagePumpForUI::MessageFilter MessageFilter;
+  typedef MessagePumpForUI::MessageFilter MessageFilter;
 #endif
 
   MessageLoopForUI() : MessageLoop(TYPE_UI) {
@@ -607,15 +603,15 @@
 
  protected:
 #if defined(USE_AURA) && defined(USE_X11) && !defined(OS_NACL)
-  friend class base::MessagePumpAuraX11;
+  friend class MessagePumpAuraX11;
 #endif
 #if defined(USE_OZONE) && !defined(OS_NACL)
-  friend class base::MessagePumpOzone;
+  friend class MessagePumpOzone;
 #endif
 
   // TODO(rvargas): Make this platform independent.
-  base::MessagePumpForUI* pump_ui() {
-    return static_cast<base::MessagePumpForUI*>(pump_.get());
+  MessagePumpForUI* pump_ui() {
+    return static_cast<MessagePumpForUI*>(pump_.get());
   }
 #endif  // !defined(OS_MACOSX)
 };
@@ -636,30 +632,30 @@
 class BASE_EXPORT MessageLoopForIO : public MessageLoop {
  public:
 #if defined(OS_WIN)
-  typedef base::MessagePumpForIO::IOHandler IOHandler;
-  typedef base::MessagePumpForIO::IOContext IOContext;
-  typedef base::MessagePumpForIO::IOObserver IOObserver;
+  typedef MessagePumpForIO::IOHandler IOHandler;
+  typedef MessagePumpForIO::IOContext IOContext;
+  typedef MessagePumpForIO::IOObserver IOObserver;
 #elif defined(OS_IOS)
-  typedef base::MessagePumpIOSForIO::Watcher Watcher;
-  typedef base::MessagePumpIOSForIO::FileDescriptorWatcher
+  typedef MessagePumpIOSForIO::Watcher Watcher;
+  typedef MessagePumpIOSForIO::FileDescriptorWatcher
       FileDescriptorWatcher;
-  typedef base::MessagePumpIOSForIO::IOObserver IOObserver;
+  typedef MessagePumpIOSForIO::IOObserver IOObserver;
 
   enum Mode {
-    WATCH_READ = base::MessagePumpIOSForIO::WATCH_READ,
-    WATCH_WRITE = base::MessagePumpIOSForIO::WATCH_WRITE,
-    WATCH_READ_WRITE = base::MessagePumpIOSForIO::WATCH_READ_WRITE
+    WATCH_READ = MessagePumpIOSForIO::WATCH_READ,
+    WATCH_WRITE = MessagePumpIOSForIO::WATCH_WRITE,
+    WATCH_READ_WRITE = MessagePumpIOSForIO::WATCH_READ_WRITE
   };
 #elif defined(OS_POSIX)
-  typedef base::MessagePumpLibevent::Watcher Watcher;
-  typedef base::MessagePumpLibevent::FileDescriptorWatcher
+  typedef MessagePumpLibevent::Watcher Watcher;
+  typedef MessagePumpLibevent::FileDescriptorWatcher
       FileDescriptorWatcher;
-  typedef base::MessagePumpLibevent::IOObserver IOObserver;
+  typedef MessagePumpLibevent::IOObserver IOObserver;
 
   enum Mode {
-    WATCH_READ = base::MessagePumpLibevent::WATCH_READ,
-    WATCH_WRITE = base::MessagePumpLibevent::WATCH_WRITE,
-    WATCH_READ_WRITE = base::MessagePumpLibevent::WATCH_READ_WRITE
+    WATCH_READ = MessagePumpLibevent::WATCH_READ,
+    WATCH_WRITE = MessagePumpLibevent::WATCH_WRITE,
+    WATCH_READ_WRITE = MessagePumpLibevent::WATCH_READ_WRITE
   };
 
 #endif
@@ -690,8 +686,8 @@
 
  protected:
   // TODO(rvargas): Make this platform independent.
-  base::MessagePumpForIO* pump_io() {
-    return static_cast<base::MessagePumpForIO*>(pump_.get());
+  MessagePumpForIO* pump_io() {
+    return static_cast<MessagePumpForIO*>(pump_.get());
   }
 
 #elif defined(OS_IOS)
@@ -703,8 +699,8 @@
                            Watcher *delegate);
 
  private:
-  base::MessagePumpIOSForIO* pump_io() {
-    return static_cast<base::MessagePumpIOSForIO*>(pump_.get());
+  MessagePumpIOSForIO* pump_io() {
+    return static_cast<MessagePumpIOSForIO*>(pump_.get());
   }
 
 #elif defined(OS_POSIX)
@@ -716,8 +712,8 @@
                            Watcher* delegate);
 
  private:
-  base::MessagePumpLibevent* pump_io() {
-    return static_cast<base::MessagePumpLibevent*>(pump_.get());
+  MessagePumpLibevent* pump_io() {
+    return static_cast<MessagePumpLibevent*>(pump_.get());
   }
 #endif  // defined(OS_POSIX)
 };
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index 0f85b14..504c8e3 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pending_task.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
@@ -20,7 +20,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
-#include "base/message_pump_win.h"
+#include "base/message_loop/message_pump_win.h"
 #include "base/win/scoped_handle.h"
 #endif
 
@@ -29,8 +29,8 @@
 class MessageLoopLockTest {
  public:
   static void LockWaitUnLock(MessageLoop* loop,
-                             base::WaitableEvent* caller_wait,
-                             base::WaitableEvent* caller_signal) {
+                             WaitableEvent* caller_wait,
+                             WaitableEvent* caller_signal) {
 
     loop->incoming_queue_lock_.Acquire();
     caller_wait->Signal();
@@ -121,7 +121,7 @@
   thread.Start();
   thread.message_loop()->PostTask(
       FROM_HERE,
-      base::Bind(&MessageLoopLockTest::LockWaitUnLock,
+      Bind(&MessageLoopLockTest::LockWaitUnLock,
       MessageLoop::current(),
       &wait,
       &signal));
@@ -1419,7 +1419,7 @@
 
 #if defined(OS_WIN)
 
-class DispatcherImpl : public base::MessageLoopForUI::Dispatcher {
+class DispatcherImpl : public MessageLoopForUI::Dispatcher {
  public:
   DispatcherImpl() : dispatch_count_(0) {}
 
diff --git a/base/message_loop/message_pump.cc b/base/message_loop/message_pump.cc
new file mode 100644
index 0000000..7ffc2b1
--- /dev/null
+++ b/base/message_loop/message_pump.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump.h"
+
+namespace base {
+
+MessagePump::MessagePump() {
+}
+
+MessagePump::~MessagePump() {
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump.h b/base/message_loop/message_pump.h
new file mode 100644
index 0000000..5b72232
--- /dev/null
+++ b/base/message_loop/message_pump.h
@@ -0,0 +1,129 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
+
+#include "base/base_export.h"
+#include "base/memory/ref_counted.h"
+
+namespace base {
+
+class TimeTicks;
+
+class BASE_EXPORT MessagePump : public RefCountedThreadSafe<MessagePump> {
+ public:
+  // Please see the comments above the Run method for an illustration of how
+  // these delegate methods are used.
+  class BASE_EXPORT Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    // Called from within Run in response to ScheduleWork or when the message
+    // pump would otherwise call DoDelayedWork.  Returns true to indicate that
+    // work was done.  DoDelayedWork will still be called if DoWork returns
+    // true, but DoIdleWork will not.
+    virtual bool DoWork() = 0;
+
+    // Called from within Run in response to ScheduleDelayedWork or when the
+    // message pump would otherwise sleep waiting for more work.  Returns true
+    // to indicate that delayed work was done.  DoIdleWork will not be called
+    // if DoDelayedWork returns true.  Upon return |next_delayed_work_time|
+    // indicates the time when DoDelayedWork should be called again.  If
+    // |next_delayed_work_time| is null (per Time::is_null), then the queue of
+    // future delayed work (timer events) is currently empty, and no additional
+    // calls to this function need to be scheduled.
+    virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) = 0;
+
+    // Called from within Run just before the message pump goes to sleep.
+    // Returns true to indicate that idle work was done.
+    virtual bool DoIdleWork() = 0;
+  };
+
+  MessagePump();
+
+  // The Run method is called to enter the message pump's run loop.
+  //
+  // Within the method, the message pump is responsible for processing native
+  // messages as well as for giving cycles to the delegate periodically.  The
+  // message pump should take care to mix delegate callbacks with native
+  // message processing so neither type of event starves the other of cycles.
+  //
+  // The anatomy of a typical run loop:
+  //
+  //   for (;;) {
+  //     bool did_work = DoInternalWork();
+  //     if (should_quit_)
+  //       break;
+  //
+  //     did_work |= delegate_->DoWork();
+  //     if (should_quit_)
+  //       break;
+  //
+  //     TimeTicks next_time;
+  //     did_work |= delegate_->DoDelayedWork(&next_time);
+  //     if (should_quit_)
+  //       break;
+  //
+  //     if (did_work)
+  //       continue;
+  //
+  //     did_work = delegate_->DoIdleWork();
+  //     if (should_quit_)
+  //       break;
+  //
+  //     if (did_work)
+  //       continue;
+  //
+  //     WaitForWork();
+  //   }
+  //
+  // Here, DoInternalWork is some private method of the message pump that is
+  // responsible for dispatching the next UI message or notifying the next IO
+  // completion (for example).  WaitForWork is a private method that simply
+  // blocks until there is more work of any type to do.
+  //
+  // Notice that the run loop cycles between calling DoInternalWork, DoWork,
+  // and DoDelayedWork methods.  This helps ensure that none of these work
+  // queues starve the others.  This is important for message pumps that are
+  // used to drive animations, for example.
+  //
+  // Notice also that after each callout to foreign code, the run loop checks
+  // to see if it should quit.  The Quit method is responsible for setting this
+  // flag.  No further work is done once the quit flag is set.
+  //
+  // NOTE: Care must be taken to handle Run being called again from within any
+  // of the callouts to foreign code.  Native message pumps may also need to
+  // deal with other native message pumps being run outside their control
+  // (e.g., the MessageBox API on Windows pumps UI messages!).  To be specific,
+  // the callouts (DoWork and DoDelayedWork) MUST still be provided even in
+  // nested sub-loops that are "seemingly" outside the control of this message
+  // pump.  DoWork in particular must never be starved for time slices unless
+  // it returns false (meaning it has run out of things to do).
+  //
+  virtual void Run(Delegate* delegate) = 0;
+
+  // Quit immediately from the most recently entered run loop.  This method may
+  // only be used on the thread that called Run.
+  virtual void Quit() = 0;
+
+  // Schedule a DoWork callback to happen reasonably soon.  Does nothing if a
+  // DoWork callback is already scheduled.  This method may be called from any
+  // thread.  Once this call is made, DoWork should not be "starved" at least
+  // until it returns a value of false.
+  virtual void ScheduleWork() = 0;
+
+  // Schedule a DoDelayedWork callback to happen at the specified time,
+  // cancelling any pending DoDelayedWork callback.  This method may only be
+  // used on the thread that called Run.
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) = 0;
+
+ protected:
+  virtual ~MessagePump();
+  friend class RefCountedThreadSafe<MessagePump>;
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
diff --git a/base/message_loop/message_pump_android.cc b/base/message_loop/message_pump_android.cc
new file mode 100644
index 0000000..d7bf9a9
--- /dev/null
+++ b/base/message_loop/message_pump_android.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_android.h"
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/time.h"
+#include "jni/SystemMessageHandler_jni.h"
+
+using base::android::ScopedJavaLocalRef;
+
+namespace {
+
+base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >
+    g_system_message_handler_obj = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// ----------------------------------------------------------------------------
+// Native JNI methods called by Java.
+// ----------------------------------------------------------------------------
+// This method can not move to anonymous namespace as it has been declared as
+// 'static' in system_message_handler_jni.h.
+static jboolean DoRunLoopOnce(JNIEnv* env, jobject obj, jint native_delegate) {
+  base::MessagePump::Delegate* delegate =
+      reinterpret_cast<base::MessagePump::Delegate*>(native_delegate);
+  DCHECK(delegate);
+  // This is based on MessagePumpForUI::DoRunLoop() from desktop.
+  // Note however that our system queue is handled in the java side.
+  // In desktop we inspect and process a single system message and then
+  // we call DoWork() / DoDelayedWork().
+  // On Android, the java message queue may contain messages for other handlers
+  // that will be processed before calling here again.
+  bool more_work_is_plausible = delegate->DoWork();
+
+  // This is the time when we need to do delayed work.
+  base::TimeTicks delayed_work_time;
+  more_work_is_plausible |= delegate->DoDelayedWork(&delayed_work_time);
+
+  // This is a major difference between android and other platforms: since we
+  // can't inspect it and process just one single message, instead we'll yeld
+  // the callstack, and post a message to call us back soon.
+  if (more_work_is_plausible)
+    return true;
+
+  more_work_is_plausible = delegate->DoIdleWork();
+  if (!more_work_is_plausible && !delayed_work_time.is_null()) {
+    // We only set the timer here as returning true would post a message.
+    jlong millis =
+        (delayed_work_time - base::TimeTicks::Now()).InMillisecondsRoundedUp();
+    Java_SystemMessageHandler_setDelayedTimer(env, obj, millis);
+  }
+  return more_work_is_plausible;
+}
+
+namespace base {
+
+MessagePumpForUI::MessagePumpForUI()
+    : run_loop_(NULL) {
+}
+
+MessagePumpForUI::~MessagePumpForUI() {
+}
+
+void MessagePumpForUI::Run(Delegate* delegate) {
+  NOTREACHED() << "UnitTests should rely on MessagePumpForUIStub in"
+      " test_stub_android.h";
+}
+
+void MessagePumpForUI::Start(Delegate* delegate) {
+  run_loop_ = new RunLoop();
+  // Since the RunLoop was just created above, BeforeRun should be guaranteed to
+  // return true (it only returns false if the RunLoop has been Quit already).
+  if (!run_loop_->BeforeRun())
+    NOTREACHED();
+
+  DCHECK(g_system_message_handler_obj.Get().is_null());
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  DCHECK(env);
+
+  g_system_message_handler_obj.Get().Reset(
+      Java_SystemMessageHandler_create(env, reinterpret_cast<jint>(delegate)));
+}
+
+void MessagePumpForUI::Quit() {
+  if (!g_system_message_handler_obj.Get().is_null()) {
+    JNIEnv* env = base::android::AttachCurrentThread();
+    DCHECK(env);
+
+    Java_SystemMessageHandler_removeTimer(env,
+        g_system_message_handler_obj.Get().obj());
+    g_system_message_handler_obj.Get().Reset();
+  }
+
+  if (run_loop_) {
+    run_loop_->AfterRun();
+    delete run_loop_;
+    run_loop_ = NULL;
+  }
+}
+
+void MessagePumpForUI::ScheduleWork() {
+  DCHECK(!g_system_message_handler_obj.Get().is_null());
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  DCHECK(env);
+
+  Java_SystemMessageHandler_setTimer(env,
+      g_system_message_handler_obj.Get().obj());
+}
+
+void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
+  DCHECK(!g_system_message_handler_obj.Get().is_null());
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  DCHECK(env);
+
+  jlong millis =
+      (delayed_work_time - TimeTicks::Now()).InMillisecondsRoundedUp();
+  // Note that we're truncating to milliseconds as required by the java side,
+  // even though delayed_work_time is microseconds resolution.
+  Java_SystemMessageHandler_setDelayedTimer(env,
+      g_system_message_handler_obj.Get().obj(), millis);
+}
+
+// static
+bool MessagePumpForUI::RegisterBindings(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_android.h b/base/message_loop/message_pump_android.h
new file mode 100644
index 0000000..fd934a7
--- /dev/null
+++ b/base/message_loop/message_pump_android.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_pump.h"
+
+namespace base {
+
+class RunLoop;
+class TimeTicks;
+
+// This class implements a MessagePump needed for TYPE_UI MessageLoops on
+// OS_ANDROID platform.
+class BASE_EXPORT MessagePumpForUI : public MessagePump {
+ public:
+  MessagePumpForUI();
+
+  virtual void Run(Delegate* delegate) OVERRIDE;
+  virtual void Quit() OVERRIDE;
+  virtual void ScheduleWork() OVERRIDE;
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+
+  virtual void Start(Delegate* delegate);
+
+  static bool RegisterBindings(JNIEnv* env);
+
+ protected:
+  virtual ~MessagePumpForUI();
+
+ private:
+  RunLoop* run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpForUI);
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
diff --git a/base/message_loop/message_pump_aurax11.cc b/base/message_loop/message_pump_aurax11.cc
new file mode 100644
index 0000000..70cae64
--- /dev/null
+++ b/base/message_loop/message_pump_aurax11.cc
@@ -0,0 +1,307 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_aurax11.h"
+
+#include <glib.h>
+#include <X11/X.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/XKBlib.h>
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+
+namespace base {
+
+namespace {
+
+gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
+  if (XPending(MessagePumpAuraX11::GetDefaultXDisplay()))
+    *timeout_ms = 0;
+  else
+    *timeout_ms = -1;
+  return FALSE;
+}
+
+gboolean XSourceCheck(GSource* source) {
+  return XPending(MessagePumpAuraX11::GetDefaultXDisplay());
+}
+
+gboolean XSourceDispatch(GSource* source,
+                         GSourceFunc unused_func,
+                         gpointer data) {
+  MessagePumpAuraX11* pump = static_cast<MessagePumpAuraX11*>(data);
+  return pump->DispatchXEvents();
+}
+
+GSourceFuncs XSourceFuncs = {
+  XSourcePrepare,
+  XSourceCheck,
+  XSourceDispatch,
+  NULL
+};
+
+// The connection is essentially a global that's accessed through a static
+// method and destroyed whenever ~MessagePumpAuraX11() is called. We do this
+// for historical reasons so user code can call
+// MessagePumpForUI::GetDefaultXDisplay() where MessagePumpForUI is a typedef
+// to whatever type in the current build.
+//
+// TODO(erg): This can be changed to something more sane like
+// MessagePumpAuraX11::Current()->display() once MessagePumpGtk goes away.
+Display* g_xdisplay = NULL;
+int g_xinput_opcode = -1;
+
+bool InitializeXInput2Internal() {
+  Display* display = MessagePumpAuraX11::GetDefaultXDisplay();
+  if (!display)
+    return false;
+
+  int event, err;
+
+  int xiopcode;
+  if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
+    DVLOG(1) << "X Input extension not available.";
+    return false;
+  }
+  g_xinput_opcode = xiopcode;
+
+#if defined(USE_XI2_MT)
+  // USE_XI2_MT also defines the required XI2 minor minimum version.
+  int major = 2, minor = USE_XI2_MT;
+#else
+  int major = 2, minor = 0;
+#endif
+  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
+    DVLOG(1) << "XInput2 not supported in the server.";
+    return false;
+  }
+#if defined(USE_XI2_MT)
+  if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
+    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
+            << "But 2." << USE_XI2_MT << " is required.";
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+Window FindEventTarget(const NativeEvent& xev) {
+  Window target = xev->xany.window;
+  if (xev->type == GenericEvent &&
+      static_cast<XIEvent*>(xev->xcookie.data)->extension == g_xinput_opcode) {
+    target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
+  }
+  return target;
+}
+
+bool InitializeXInput2() {
+  static bool xinput2_supported = InitializeXInput2Internal();
+  return xinput2_supported;
+}
+
+bool InitializeXkb() {
+  Display* display = MessagePumpAuraX11::GetDefaultXDisplay();
+  if (!display)
+    return false;
+
+  int opcode, event, error;
+  int major = XkbMajorVersion;
+  int minor = XkbMinorVersion;
+  if (!XkbQueryExtension(display, &opcode, &event, &error, &major, &minor)) {
+    DVLOG(1) << "Xkb extension not available.";
+    return false;
+  }
+
+  // Ask the server not to send KeyRelease event when the user holds down a key.
+  // crbug.com/138092
+  Bool supported_return;
+  if (!XkbSetDetectableAutoRepeat(display, True, &supported_return)) {
+    DVLOG(1) << "XKB not supported in the server.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(),
+    x_source_(NULL) {
+  InitializeXInput2();
+  InitializeXkb();
+  InitXSource();
+
+  // Can't put this in the initializer list because g_xdisplay may not exist
+  // until after InitXSource().
+  x_root_window_ = DefaultRootWindow(g_xdisplay);
+}
+
+// static
+Display* MessagePumpAuraX11::GetDefaultXDisplay() {
+  if (!g_xdisplay)
+    g_xdisplay = XOpenDisplay(NULL);
+  return g_xdisplay;
+}
+
+// static
+bool MessagePumpAuraX11::HasXInput2() {
+  return InitializeXInput2();
+}
+
+// static
+MessagePumpAuraX11* MessagePumpAuraX11::Current() {
+  MessageLoopForUI* loop = MessageLoopForUI::current();
+  return static_cast<MessagePumpAuraX11*>(loop->pump_ui());
+}
+
+void MessagePumpAuraX11::AddDispatcherForWindow(
+    MessagePumpDispatcher* dispatcher,
+    unsigned long xid) {
+  dispatchers_.insert(std::make_pair(xid, dispatcher));
+}
+
+void MessagePumpAuraX11::RemoveDispatcherForWindow(unsigned long xid) {
+  dispatchers_.erase(xid);
+}
+
+void MessagePumpAuraX11::AddDispatcherForRootWindow(
+    MessagePumpDispatcher* dispatcher) {
+  root_window_dispatchers_.AddObserver(dispatcher);
+}
+
+void MessagePumpAuraX11::RemoveDispatcherForRootWindow(
+    MessagePumpDispatcher* dispatcher) {
+  root_window_dispatchers_.RemoveObserver(dispatcher);
+}
+
+bool MessagePumpAuraX11::DispatchXEvents() {
+  Display* display = GetDefaultXDisplay();
+  DCHECK(display);
+  MessagePumpDispatcher* dispatcher =
+      GetDispatcher() ? GetDispatcher() : this;
+
+  // In the general case, we want to handle all pending events before running
+  // the tasks. This is what happens in the message_pump_glib case.
+  while (XPending(display)) {
+    XEvent xev;
+    XNextEvent(display, &xev);
+    if (dispatcher && ProcessXEvent(dispatcher, &xev))
+      return TRUE;
+  }
+  return TRUE;
+}
+
+void MessagePumpAuraX11::BlockUntilWindowMapped(unsigned long xid) {
+  XEvent event;
+
+  Display* display = GetDefaultXDisplay();
+  DCHECK(display);
+
+  MessagePumpDispatcher* dispatcher =
+      GetDispatcher() ? GetDispatcher() : this;
+
+  do {
+    // Block until there's a message of |event_mask| type on |w|. Then remove
+    // it from the queue and stuff it in |event|.
+    XWindowEvent(display, xid, StructureNotifyMask, &event);
+    ProcessXEvent(dispatcher, &event);
+  } while (event.type != MapNotify);
+}
+
+MessagePumpAuraX11::~MessagePumpAuraX11() {
+  g_source_destroy(x_source_);
+  g_source_unref(x_source_);
+  XCloseDisplay(g_xdisplay);
+  g_xdisplay = NULL;
+}
+
+void MessagePumpAuraX11::InitXSource() {
+  // CHECKs are to help track down crbug.com/113106.
+  CHECK(!x_source_);
+  Display* display = GetDefaultXDisplay();
+  CHECK(display) << "Unable to get connection to X server";
+  x_poll_.reset(new GPollFD());
+  CHECK(x_poll_.get());
+  x_poll_->fd = ConnectionNumber(display);
+  x_poll_->events = G_IO_IN;
+
+  x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource));
+  g_source_add_poll(x_source_, x_poll_.get());
+  g_source_set_can_recurse(x_source_, TRUE);
+  g_source_set_callback(x_source_, NULL, this, NULL);
+  g_source_attach(x_source_, g_main_context_default());
+}
+
+bool MessagePumpAuraX11::ProcessXEvent(MessagePumpDispatcher* dispatcher,
+                                       XEvent* xev) {
+  bool should_quit = false;
+
+  bool have_cookie = false;
+  if (xev->type == GenericEvent &&
+      XGetEventData(xev->xgeneric.display, &xev->xcookie)) {
+    have_cookie = true;
+  }
+
+  if (!WillProcessXEvent(xev)) {
+    if (!dispatcher->Dispatch(xev)) {
+      should_quit = true;
+      Quit();
+    }
+    DidProcessXEvent(xev);
+  }
+
+  if (have_cookie) {
+    XFreeEventData(xev->xgeneric.display, &xev->xcookie);
+  }
+
+  return should_quit;
+}
+
+bool MessagePumpAuraX11::WillProcessXEvent(XEvent* xevent) {
+  if (!observers().might_have_observers())
+    return false;
+  ObserverListBase<MessagePumpObserver>::Iterator it(observers());
+  MessagePumpObserver* obs;
+  while ((obs = it.GetNext()) != NULL) {
+    if (obs->WillProcessEvent(xevent))
+      return true;
+  }
+  return false;
+}
+
+void MessagePumpAuraX11::DidProcessXEvent(XEvent* xevent) {
+  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent));
+}
+
+MessagePumpDispatcher* MessagePumpAuraX11::GetDispatcherForXEvent(
+    const NativeEvent& xev) const {
+  ::Window x_window = FindEventTarget(xev);
+  DispatchersMap::const_iterator it = dispatchers_.find(x_window);
+  return it != dispatchers_.end() ? it->second : NULL;
+}
+
+bool MessagePumpAuraX11::Dispatch(const NativeEvent& xev) {
+  // MappingNotify events (meaning that the keyboard or pointer buttons have
+  // been remapped) aren't associated with a window; send them to all
+  // dispatchers.
+  if (xev->type == MappingNotify) {
+    for (DispatchersMap::const_iterator it = dispatchers_.begin();
+         it != dispatchers_.end(); ++it) {
+      it->second->Dispatch(xev);
+    }
+    return true;
+  }
+
+  if (FindEventTarget(xev) == x_root_window_) {
+    FOR_EACH_OBSERVER(MessagePumpDispatcher, root_window_dispatchers_,
+                      Dispatch(xev));
+    return true;
+  }
+  MessagePumpDispatcher* dispatcher = GetDispatcherForXEvent(xev);
+  return dispatcher ? dispatcher->Dispatch(xev) : true;
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_aurax11.h b/base/message_loop/message_pump_aurax11.h
new file mode 100644
index 0000000..cec6934
--- /dev/null
+++ b/base/message_loop/message_pump_aurax11.h
@@ -0,0 +1,122 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_AURAX11_H
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_AURAX11_H
+
+#include <bitset>
+#include <map>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_pump.h"
+#include "base/message_loop/message_pump_dispatcher.h"
+#include "base/message_loop/message_pump_glib.h"
+#include "base/message_loop/message_pump_observer.h"
+#include "base/observer_list.h"
+
+// It would be nice to include the X11 headers here so that we use Window
+// instead of its typedef of unsigned long, but we can't because everything in
+// chrome includes us through base/message_loop.h, and X11's crappy #define
+// heavy headers muck up half of chrome.
+
+typedef struct _GPollFD GPollFD;
+typedef struct _GSource GSource;
+typedef struct _XDisplay Display;
+
+namespace base {
+
+// This class implements a message-pump for dispatching X events.
+//
+// If there's a current dispatcher given through RunWithDispatcher(), that
+// dispatcher receives events. Otherwise, we route to messages to dispatchers
+// who have subscribed to messages from a specific X11 window.
+class BASE_EXPORT MessagePumpAuraX11 : public MessagePumpGlib,
+                                       public MessagePumpDispatcher {
+ public:
+  MessagePumpAuraX11();
+
+  // Returns default X Display.
+  static Display* GetDefaultXDisplay();
+
+  // Returns true if the system supports XINPUT2.
+  static bool HasXInput2();
+
+  // Returns the UI message pump.
+  static MessagePumpAuraX11* Current();
+
+  // Adds/Removes |dispatcher| for the |xid|. This will route all messages from
+  // the window |xid| to |dispatcher.
+  void AddDispatcherForWindow(MessagePumpDispatcher* dispatcher,
+                              unsigned long xid);
+  void RemoveDispatcherForWindow(unsigned long xid);
+
+  // Adds/Removes |dispatcher| to receive all events sent to the X root
+  // window. A root window can have multiple dispatchers, and events on root
+  // windows will be dispatched to all.
+  void AddDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
+  void RemoveDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
+
+  // Internal function. Called by the glib source dispatch function. Processes
+  // all available X events.
+  bool DispatchXEvents();
+
+  // Blocks on the X11 event queue until we receive notification from the
+  // xserver that |w| has been mapped; StructureNotifyMask events on |w| are
+  // pulled out from the queue and dispatched out of order.
+  //
+  // For those that know X11, this is really a wrapper around XWindowEvent
+  // which still makes sure the preempted event is dispatched instead of
+  // dropped on the floor. This method exists because mapping a window is
+  // asynchronous (and we receive an XEvent when mapped), while there are also
+  // functions which require a mapped window.
+  void BlockUntilWindowMapped(unsigned long xid);
+
+ protected:
+  virtual ~MessagePumpAuraX11();
+
+ private:
+  typedef std::map<unsigned long, MessagePumpDispatcher*> DispatchersMap;
+
+  // Initializes the glib event source for X.
+  void InitXSource();
+
+  // Dispatches the XEvent and returns true if we should exit the current loop
+  // of message processing.
+  bool ProcessXEvent(MessagePumpDispatcher* dispatcher, XEvent* event);
+
+  // Sends the event to the observers. If an observer returns true, then it does
+  // not send the event to any other observers and returns true. Returns false
+  // if no observer returns true.
+  bool WillProcessXEvent(XEvent* xevent);
+  void DidProcessXEvent(XEvent* xevent);
+
+  // Returns the Dispatcher based on the event's target window.
+  MessagePumpDispatcher* GetDispatcherForXEvent(const NativeEvent& xev) const;
+
+  // Overridden from MessagePumpDispatcher:
+  virtual bool Dispatch(const NativeEvent& event) OVERRIDE;
+
+  // The event source for X events.
+  GSource* x_source_;
+
+  // The poll attached to |x_source_|.
+  scoped_ptr<GPollFD> x_poll_;
+
+  DispatchersMap dispatchers_;
+
+  // Dispatch calls can cause addition of new dispatchers as we iterate
+  // through them. Use ObserverList to ensure the iterator remains valid across
+  // additions.
+  ObserverList<MessagePumpDispatcher> root_window_dispatchers_;
+
+  unsigned long x_root_window_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpAuraX11);
+};
+
+typedef MessagePumpAuraX11 MessagePumpForUI;
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_AURAX11_H
diff --git a/base/message_loop/message_pump_default.cc b/base/message_loop/message_pump_default.cc
new file mode 100644
index 0000000..b36ff21
--- /dev/null
+++ b/base/message_loop/message_pump_default.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_default.h"
+
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+
+namespace base {
+
+MessagePumpDefault::MessagePumpDefault()
+    : keep_running_(true),
+      event_(false, false) {
+}
+
+void MessagePumpDefault::Run(Delegate* delegate) {
+  DCHECK(keep_running_) << "Quit must have been called outside of Run!";
+
+  for (;;) {
+#if defined(OS_MACOSX)
+    mac::ScopedNSAutoreleasePool autorelease_pool;
+#endif
+
+    bool did_work = delegate->DoWork();
+    if (!keep_running_)
+      break;
+
+    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    did_work = delegate->DoIdleWork();
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    ThreadRestrictions::ScopedAllowWait allow_wait;
+    if (delayed_work_time_.is_null()) {
+      event_.Wait();
+    } else {
+      TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
+      if (delay > TimeDelta()) {
+        event_.TimedWait(delay);
+      } else {
+        // It looks like delayed_work_time_ indicates a time in the past, so we
+        // need to call DoDelayedWork now.
+        delayed_work_time_ = TimeTicks();
+      }
+    }
+    // Since event_ is auto-reset, we don't need to do anything special here
+    // other than service each delegate method.
+  }
+
+  keep_running_ = true;
+}
+
+void MessagePumpDefault::Quit() {
+  keep_running_ = false;
+}
+
+void MessagePumpDefault::ScheduleWork() {
+  // Since this can be called on any thread, we need to ensure that our Run
+  // loop wakes up.
+  event_.Signal();
+}
+
+void MessagePumpDefault::ScheduleDelayedWork(
+    const TimeTicks& delayed_work_time) {
+  // We know that we can't be blocked on Wait right now since this method can
+  // only be called on the same thread as Run, so we only need to update our
+  // record of how long to sleep when we do sleep.
+  delayed_work_time_ = delayed_work_time;
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_default.h b/base/message_loop/message_pump_default.h
new file mode 100644
index 0000000..dd65973
--- /dev/null
+++ b/base/message_loop/message_pump_default.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_
+
+#include "base/message_loop/message_pump.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/time.h"
+
+namespace base {
+
+class MessagePumpDefault : public MessagePump {
+ public:
+  MessagePumpDefault();
+
+  // MessagePump methods:
+  virtual void Run(Delegate* delegate) OVERRIDE;
+  virtual void Quit() OVERRIDE;
+  virtual void ScheduleWork() OVERRIDE;
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+
+ protected:
+  virtual ~MessagePumpDefault() {}
+
+ private:
+  // This flag is set to false when Run should return.
+  bool keep_running_;
+
+  // Used to sleep until there is more work to do.
+  WaitableEvent event_;
+
+  // The time at which we should call DoDelayedWork.
+  TimeTicks delayed_work_time_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpDefault);
+};
+
+}  // namespace base
+
+#endif  // BASE__MESSAGE_LOOPMESSAGE_PUMP_DEFAULT_H_
diff --git a/base/message_loop/message_pump_dispatcher.h b/base/message_loop/message_pump_dispatcher.h
new file mode 100644
index 0000000..e49fa4f
--- /dev/null
+++ b/base/message_loop/message_pump_dispatcher.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
+
+#include "base/base_export.h"
+#include "base/event_types.h"
+
+namespace base {
+
+// Dispatcher is used during a nested invocation of Run to dispatch events when
+// |RunLoop(dispatcher).Run()| is used.  If |RunLoop().Run()| is invoked,
+// MessageLoop does not dispatch events (or invoke TranslateMessage), rather
+// every message is passed to Dispatcher's Dispatch method for dispatch. It is
+// up to the Dispatcher whether or not to dispatch the event.
+//
+// The nested loop is exited by either posting a quit, or returning false
+// from Dispatch.
+class BASE_EXPORT MessagePumpDispatcher {
+ public:
+  virtual ~MessagePumpDispatcher() {}
+
+  // Dispatches the event. If true is returned processing continues as
+  // normal. If false is returned, the nested loop exits immediately.
+  virtual bool Dispatch(const NativeEvent& event) = 0;
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
diff --git a/base/message_loop/message_pump_glib.cc b/base/message_loop/message_pump_glib.cc
new file mode 100644
index 0000000..de012fd
--- /dev/null
+++ b/base/message_loop/message_pump_glib.cc
@@ -0,0 +1,334 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_glib.h"
+
+#include <fcntl.h>
+#include <math.h>
+
+#include <glib.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+namespace {
+
+// Return a timeout suitable for the glib loop, -1 to block forever,
+// 0 to return right away, or a timeout in milliseconds from now.
+int GetTimeIntervalMilliseconds(const TimeTicks& from) {
+  if (from.is_null())
+    return -1;
+
+  // Be careful here.  TimeDelta has a precision of microseconds, but we want a
+  // value in milliseconds.  If there are 5.5ms left, should the delay be 5 or
+  // 6?  It should be 6 to avoid executing delayed work too early.
+  int delay = static_cast<int>(
+      ceil((from - TimeTicks::Now()).InMillisecondsF()));
+
+  // If this value is negative, then we need to run delayed work soon.
+  return delay < 0 ? 0 : delay;
+}
+
+// A brief refresher on GLib:
+//     GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize.
+// On each iteration of the GLib pump, it calls each source's Prepare function.
+// This function should return TRUE if it wants GLib to call its Dispatch, and
+// FALSE otherwise.  It can also set a timeout in this case for the next time
+// Prepare should be called again (it may be called sooner).
+//     After the Prepare calls, GLib does a poll to check for events from the
+// system.  File descriptors can be attached to the sources.  The poll may block
+// if none of the Prepare calls returned TRUE.  It will block indefinitely, or
+// by the minimum time returned by a source in Prepare.
+//     After the poll, GLib calls Check for each source that returned FALSE
+// from Prepare.  The return value of Check has the same meaning as for Prepare,
+// making Check a second chance to tell GLib we are ready for Dispatch.
+//     Finally, GLib calls Dispatch for each source that is ready.  If Dispatch
+// returns FALSE, GLib will destroy the source.  Dispatch calls may be recursive
+// (i.e., you can call Run from them), but Prepare and Check cannot.
+//     Finalize is called when the source is destroyed.
+// NOTE: It is common for subsytems to want to process pending events while
+// doing intensive work, for example the flash plugin. They usually use the
+// following pattern (recommended by the GTK docs):
+// while (gtk_events_pending()) {
+//   gtk_main_iteration();
+// }
+//
+// gtk_events_pending just calls g_main_context_pending, which does the
+// following:
+// - Call prepare on all the sources.
+// - Do the poll with a timeout of 0 (not blocking).
+// - Call check on all the sources.
+// - *Does not* call dispatch on the sources.
+// - Return true if any of prepare() or check() returned true.
+//
+// gtk_main_iteration just calls g_main_context_iteration, which does the whole
+// thing, respecting the timeout for the poll (and block, although it is
+// expected not to if gtk_events_pending returned true), and call dispatch.
+//
+// Thus it is important to only return true from prepare or check if we
+// actually have events or work to do. We also need to make sure we keep
+// internal state consistent so that if prepare/check return true when called
+// from gtk_events_pending, they will still return true when called right
+// after, from gtk_main_iteration.
+//
+// For the GLib pump we try to follow the Windows UI pump model:
+// - Whenever we receive a wakeup event or the timer for delayed work expires,
+// we run DoWork and/or DoDelayedWork. That part will also run in the other
+// event pumps.
+// - We also run DoWork, DoDelayedWork, and possibly DoIdleWork in the main
+// loop, around event handling.
+
+struct WorkSource : public GSource {
+  MessagePumpGlib* pump;
+};
+
+gboolean WorkSourcePrepare(GSource* source,
+                           gint* timeout_ms) {
+  *timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare();
+  // We always return FALSE, so that our timeout is honored.  If we were
+  // to return TRUE, the timeout would be considered to be 0 and the poll
+  // would never block.  Once the poll is finished, Check will be called.
+  return FALSE;
+}
+
+gboolean WorkSourceCheck(GSource* source) {
+  // Only return TRUE if Dispatch should be called.
+  return static_cast<WorkSource*>(source)->pump->HandleCheck();
+}
+
+gboolean WorkSourceDispatch(GSource* source,
+                            GSourceFunc unused_func,
+                            gpointer unused_data) {
+
+  static_cast<WorkSource*>(source)->pump->HandleDispatch();
+  // Always return TRUE so our source stays registered.
+  return TRUE;
+}
+
+// I wish these could be const, but g_source_new wants non-const.
+GSourceFuncs WorkSourceFuncs = {
+  WorkSourcePrepare,
+  WorkSourceCheck,
+  WorkSourceDispatch,
+  NULL
+};
+
+}  // namespace
+
+struct MessagePumpGlib::RunState {
+  Delegate* delegate;
+  MessagePumpDispatcher* dispatcher;
+
+  // Used to flag that the current Run() invocation should return ASAP.
+  bool should_quit;
+
+  // Used to count how many Run() invocations are on the stack.
+  int run_depth;
+
+  // This keeps the state of whether the pump got signaled that there was new
+  // work to be done. Since we eat the message on the wake up pipe as soon as
+  // we get it, we keep that state here to stay consistent.
+  bool has_work;
+};
+
+MessagePumpGlib::MessagePumpGlib()
+    : state_(NULL),
+      context_(g_main_context_default()),
+      wakeup_gpollfd_(new GPollFD) {
+  // Create our wakeup pipe, which is used to flag when work was scheduled.
+  int fds[2];
+  int ret = pipe(fds);
+  DCHECK_EQ(ret, 0);
+  (void)ret;  // Prevent warning in release mode.
+
+  wakeup_pipe_read_  = fds[0];
+  wakeup_pipe_write_ = fds[1];
+  wakeup_gpollfd_->fd = wakeup_pipe_read_;
+  wakeup_gpollfd_->events = G_IO_IN;
+
+  work_source_ = g_source_new(&WorkSourceFuncs, sizeof(WorkSource));
+  static_cast<WorkSource*>(work_source_)->pump = this;
+  g_source_add_poll(work_source_, wakeup_gpollfd_.get());
+  // Use a low priority so that we let other events in the queue go first.
+  g_source_set_priority(work_source_, G_PRIORITY_DEFAULT_IDLE);
+  // This is needed to allow Run calls inside Dispatch.
+  g_source_set_can_recurse(work_source_, TRUE);
+  g_source_attach(work_source_, context_);
+}
+
+void MessagePumpGlib::RunWithDispatcher(Delegate* delegate,
+                                        MessagePumpDispatcher* dispatcher) {
+#ifndef NDEBUG
+  // Make sure we only run this on one thread. X/GTK only has one message pump
+  // so we can only have one UI loop per process.
+  static PlatformThreadId thread_id = PlatformThread::CurrentId();
+  DCHECK(thread_id == PlatformThread::CurrentId()) <<
+      "Running MessagePumpGlib on two different threads; "
+      "this is unsupported by GLib!";
+#endif
+
+  RunState state;
+  state.delegate = delegate;
+  state.dispatcher = dispatcher;
+  state.should_quit = false;
+  state.run_depth = state_ ? state_->run_depth + 1 : 1;
+  state.has_work = false;
+
+  RunState* previous_state = state_;
+  state_ = &state;
+
+  // We really only do a single task for each iteration of the loop.  If we
+  // have done something, assume there is likely something more to do.  This
+  // will mean that we don't block on the message pump until there was nothing
+  // more to do.  We also set this to true to make sure not to block on the
+  // first iteration of the loop, so RunUntilIdle() works correctly.
+  bool more_work_is_plausible = true;
+
+  // We run our own loop instead of using g_main_loop_quit in one of the
+  // callbacks.  This is so we only quit our own loops, and we don't quit
+  // nested loops run by others.  TODO(deanm): Is this what we want?
+  for (;;) {
+    // Don't block if we think we have more work to do.
+    bool block = !more_work_is_plausible;
+
+    more_work_is_plausible = g_main_context_iteration(context_, block);
+    if (state_->should_quit)
+      break;
+
+    more_work_is_plausible |= state_->delegate->DoWork();
+    if (state_->should_quit)
+      break;
+
+    more_work_is_plausible |=
+        state_->delegate->DoDelayedWork(&delayed_work_time_);
+    if (state_->should_quit)
+      break;
+
+    if (more_work_is_plausible)
+      continue;
+
+    more_work_is_plausible = state_->delegate->DoIdleWork();
+    if (state_->should_quit)
+      break;
+  }
+
+  state_ = previous_state;
+}
+
+// Return the timeout we want passed to poll.
+int MessagePumpGlib::HandlePrepare() {
+  // We know we have work, but we haven't called HandleDispatch yet. Don't let
+  // the pump block so that we can do some processing.
+  if (state_ &&  // state_ may be null during tests.
+      state_->has_work)
+    return 0;
+
+  // We don't think we have work to do, but make sure not to block
+  // longer than the next time we need to run delayed work.
+  return GetTimeIntervalMilliseconds(delayed_work_time_);
+}
+
+bool MessagePumpGlib::HandleCheck() {
+  if (!state_)  // state_ may be null during tests.
+    return false;
+
+  // We usually have a single message on the wakeup pipe, since we are only
+  // signaled when the queue went from empty to non-empty, but there can be
+  // two messages if a task posted a task, hence we read at most two bytes.
+  // The glib poll will tell us whether there was data, so this read
+  // shouldn't block.
+  if (wakeup_gpollfd_->revents & G_IO_IN) {
+    char msg[2];
+    const int num_bytes = HANDLE_EINTR(read(wakeup_pipe_read_, msg, 2));
+    if (num_bytes < 1) {
+      NOTREACHED() << "Error reading from the wakeup pipe.";
+    }
+    DCHECK((num_bytes == 1 && msg[0] == '!') ||
+           (num_bytes == 2 && msg[0] == '!' && msg[1] == '!'));
+    // Since we ate the message, we need to record that we have more work,
+    // because HandleCheck() may be called without HandleDispatch being called
+    // afterwards.
+    state_->has_work = true;
+  }
+
+  if (state_->has_work)
+    return true;
+
+  if (GetTimeIntervalMilliseconds(delayed_work_time_) == 0) {
+    // The timer has expired. That condition will stay true until we process
+    // that delayed work, so we don't need to record this differently.
+    return true;
+  }
+
+  return false;
+}
+
+void MessagePumpGlib::HandleDispatch() {
+  state_->has_work = false;
+  if (state_->delegate->DoWork()) {
+    // NOTE: on Windows at this point we would call ScheduleWork (see
+    // MessagePumpGlib::HandleWorkMessage in message_pump_win.cc). But here,
+    // instead of posting a message on the wakeup pipe, we can avoid the
+    // syscalls and just signal that we have more work.
+    state_->has_work = true;
+  }
+
+  if (state_->should_quit)
+    return;
+
+  state_->delegate->DoDelayedWork(&delayed_work_time_);
+}
+
+void MessagePumpGlib::AddObserver(MessagePumpObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void MessagePumpGlib::RemoveObserver(MessagePumpObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void MessagePumpGlib::Run(Delegate* delegate) {
+  RunWithDispatcher(delegate, NULL);
+}
+
+void MessagePumpGlib::Quit() {
+  if (state_) {
+    state_->should_quit = true;
+  } else {
+    NOTREACHED() << "Quit called outside Run!";
+  }
+}
+
+void MessagePumpGlib::ScheduleWork() {
+  // This can be called on any thread, so we don't want to touch any state
+  // variables as we would then need locks all over.  This ensures that if
+  // we are sleeping in a poll that we will wake up.
+  char msg = '!';
+  if (HANDLE_EINTR(write(wakeup_pipe_write_, &msg, 1)) != 1) {
+    NOTREACHED() << "Could not write to the UI message loop wakeup pipe!";
+  }
+}
+
+void MessagePumpGlib::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
+  // We need to wake up the loop in case the poll timeout needs to be
+  // adjusted.  This will cause us to try to do work, but that's ok.
+  delayed_work_time_ = delayed_work_time;
+  ScheduleWork();
+}
+
+MessagePumpGlib::~MessagePumpGlib() {
+  g_source_destroy(work_source_);
+  g_source_unref(work_source_);
+  close(wakeup_pipe_read_);
+  close(wakeup_pipe_write_);
+}
+
+MessagePumpDispatcher* MessagePumpGlib::GetDispatcher() {
+  return state_ ? state_->dispatcher : NULL;
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_glib.h b/base/message_loop/message_pump_glib.h
new file mode 100644
index 0000000..e45591b
--- /dev/null
+++ b/base/message_loop/message_pump_glib.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_
+
+#include "base/base_export.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_pump.h"
+#include "base/observer_list.h"
+#include "base/time.h"
+
+typedef struct _GMainContext GMainContext;
+typedef struct _GPollFD GPollFD;
+typedef struct _GSource GSource;
+
+namespace base {
+
+// MessagePumpObserver is notified prior to an event being dispatched. As
+// Observers are notified of every change, they have to be FAST! The platform
+// specific implementation of the class is in message_pump_gtk/message_pump_x.
+class MessagePumpObserver;
+
+// MessagePumpDispatcher is used during a nested invocation of Run to dispatch
+// events. If Run is invoked with a non-NULL MessagePumpDispatcher, MessageLoop
+// does not dispatch events (or invoke gtk_main_do_event), rather every event is
+// passed to Dispatcher's Dispatch method for dispatch. It is up to the
+// Dispatcher to dispatch, or not, the event. The platform specific
+// implementation of the class is in message_pump_gtk/message_pump_x.
+class MessagePumpDispatcher;
+
+// This class implements a base MessagePump needed for TYPE_UI MessageLoops on
+// platforms using GLib.
+class BASE_EXPORT MessagePumpGlib : public MessagePump {
+ public:
+  MessagePumpGlib();
+
+  // Like MessagePump::Run, but events are routed through dispatcher.
+  virtual void RunWithDispatcher(Delegate* delegate,
+                                 MessagePumpDispatcher* dispatcher);
+
+  // Internal methods used for processing the pump callbacks.  They are
+  // public for simplicity but should not be used directly.  HandlePrepare
+  // is called during the prepare step of glib, and returns a timeout that
+  // will be passed to the poll. HandleCheck is called after the poll
+  // has completed, and returns whether or not HandleDispatch should be called.
+  // HandleDispatch is called if HandleCheck returned true.
+  int HandlePrepare();
+  bool HandleCheck();
+  void HandleDispatch();
+
+  // Adds an Observer, which will start receiving notifications immediately.
+  void AddObserver(MessagePumpObserver* observer);
+
+  // Removes an Observer.  It is safe to call this method while an Observer is
+  // receiving a notification callback.
+  void RemoveObserver(MessagePumpObserver* observer);
+
+  // Overridden from MessagePump:
+  virtual void Run(Delegate* delegate) OVERRIDE;
+  virtual void Quit() OVERRIDE;
+  virtual void ScheduleWork() OVERRIDE;
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+
+ protected:
+  virtual ~MessagePumpGlib();
+
+  // Returns the dispatcher for the current run state (|state_->dispatcher|).
+  MessagePumpDispatcher* GetDispatcher();
+
+  ObserverList<MessagePumpObserver>& observers() { return observers_; }
+
+ private:
+  // We may make recursive calls to Run, so we save state that needs to be
+  // separate between them in this structure type.
+  struct RunState;
+
+  RunState* state_;
+
+  // This is a GLib structure that we can add event sources to.  We use the
+  // default GLib context, which is the one to which all GTK events are
+  // dispatched.
+  GMainContext* context_;
+
+  // This is the time when we need to do delayed work.
+  TimeTicks delayed_work_time_;
+
+  // The work source.  It is shared by all calls to Run and destroyed when
+  // the message pump is destroyed.
+  GSource* work_source_;
+
+  // We use a wakeup pipe to make sure we'll get out of the glib polling phase
+  // when another thread has scheduled us to do some work.  There is a glib
+  // mechanism g_main_context_wakeup, but this won't guarantee that our event's
+  // Dispatch() will be called.
+  int wakeup_pipe_read_;
+  int wakeup_pipe_write_;
+  // Use a scoped_ptr to avoid needing the definition of GPollFD in the header.
+  scoped_ptr<GPollFD> wakeup_gpollfd_;
+
+  // List of observers.
+  ObserverList<MessagePumpObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpGlib);
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc
new file mode 100644
index 0000000..cb30bb0
--- /dev/null
+++ b/base/message_loop/message_pump_glib_unittest.cc
@@ -0,0 +1,580 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_glib.h"
+
+#include <glib.h>
+#include <math.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(TOOLKIT_GTK)
+#include <gtk/gtk.h>
+#endif
+
+namespace base {
+namespace {
+
+// This class injects dummy "events" into the GLib loop. When "handled" these
+// events can run tasks. This is intended to mock gtk events (the corresponding
+// GLib source runs at the same priority).
+class EventInjector {
+ public:
+  EventInjector() : processed_events_(0) {
+    source_ = static_cast<Source*>(g_source_new(&SourceFuncs, sizeof(Source)));
+    source_->injector = this;
+    g_source_attach(source_, NULL);
+    g_source_set_can_recurse(source_, TRUE);
+  }
+
+  ~EventInjector() {
+    g_source_destroy(source_);
+    g_source_unref(source_);
+  }
+
+  int HandlePrepare() {
+    // If the queue is empty, block.
+    if (events_.empty())
+      return -1;
+    TimeDelta delta = events_[0].time - Time::NowFromSystemTime();
+    return std::max(0, static_cast<int>(ceil(delta.InMillisecondsF())));
+  }
+
+  bool HandleCheck() {
+    if (events_.empty())
+      return false;
+    return events_[0].time <= Time::NowFromSystemTime();
+  }
+
+  void HandleDispatch() {
+    if (events_.empty())
+      return;
+    Event event = events_[0];
+    events_.erase(events_.begin());
+    ++processed_events_;
+    if (!event.callback.is_null())
+      event.callback.Run();
+    else if (!event.task.is_null())
+      event.task.Run();
+  }
+
+  // Adds an event to the queue. When "handled", executes |callback|.
+  // delay_ms is relative to the last event if any, or to Now() otherwise.
+  void AddEvent(int delay_ms, const Closure& callback) {
+    AddEventHelper(delay_ms, callback, Closure());
+  }
+
+  void AddDummyEvent(int delay_ms) {
+    AddEventHelper(delay_ms, Closure(), Closure());
+  }
+
+  void AddEventAsTask(int delay_ms, const Closure& task) {
+    AddEventHelper(delay_ms, Closure(), task);
+  }
+
+  void Reset() {
+    processed_events_ = 0;
+    events_.clear();
+  }
+
+  int processed_events() const { return processed_events_; }
+
+ private:
+  struct Event {
+    Time time;
+    Closure callback;
+    Closure task;
+  };
+
+  struct Source : public GSource {
+    EventInjector* injector;
+  };
+
+  void AddEventHelper(
+      int delay_ms, const Closure& callback, const Closure& task) {
+    Time last_time;
+    if (!events_.empty())
+      last_time = (events_.end()-1)->time;
+    else
+      last_time = Time::NowFromSystemTime();
+
+    Time future = last_time + TimeDelta::FromMilliseconds(delay_ms);
+    EventInjector::Event event = {future, callback, task};
+    events_.push_back(event);
+  }
+
+  static gboolean Prepare(GSource* source, gint* timeout_ms) {
+    *timeout_ms = static_cast<Source*>(source)->injector->HandlePrepare();
+    return FALSE;
+  }
+
+  static gboolean Check(GSource* source) {
+    return static_cast<Source*>(source)->injector->HandleCheck();
+  }
+
+  static gboolean Dispatch(GSource* source,
+                           GSourceFunc unused_func,
+                           gpointer unused_data) {
+    static_cast<Source*>(source)->injector->HandleDispatch();
+    return TRUE;
+  }
+
+  Source* source_;
+  std::vector<Event> events_;
+  int processed_events_;
+  static GSourceFuncs SourceFuncs;
+  DISALLOW_COPY_AND_ASSIGN(EventInjector);
+};
+
+GSourceFuncs EventInjector::SourceFuncs = {
+  EventInjector::Prepare,
+  EventInjector::Check,
+  EventInjector::Dispatch,
+  NULL
+};
+
+void IncrementInt(int *value) {
+  ++*value;
+}
+
+// Checks how many events have been processed by the injector.
+void ExpectProcessedEvents(EventInjector* injector, int count) {
+  EXPECT_EQ(injector->processed_events(), count);
+}
+
+// Posts a task on the current message loop.
+void PostMessageLoopTask(const tracked_objects::Location& from_here,
+                         const Closure& task) {
+  MessageLoop::current()->PostTask(from_here, task);
+}
+
+// Test fixture.
+class MessagePumpGLibTest : public testing::Test {
+ public:
+  MessagePumpGLibTest() : loop_(NULL), injector_(NULL) { }
+
+  // Overridden from testing::Test:
+  virtual void SetUp() OVERRIDE {
+    loop_ = new MessageLoop(MessageLoop::TYPE_UI);
+    injector_ = new EventInjector();
+  }
+  virtual void TearDown() OVERRIDE {
+    delete injector_;
+    injector_ = NULL;
+    delete loop_;
+    loop_ = NULL;
+  }
+
+  MessageLoop* loop() const { return loop_; }
+  EventInjector* injector() const { return injector_; }
+
+ private:
+  MessageLoop* loop_;
+  EventInjector* injector_;
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpGLibTest);
+};
+
+}  // namespace
+
+TEST_F(MessagePumpGLibTest, TestQuit) {
+  // Checks that Quit works and that the basic infrastructure is working.
+
+  // Quit from a task
+  RunLoop().RunUntilIdle();
+  EXPECT_EQ(0, injector()->processed_events());
+
+  injector()->Reset();
+  // Quit from an event
+  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+  loop()->Run();
+  EXPECT_EQ(1, injector()->processed_events());
+}
+
+TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) {
+  // Checks that tasks posted by events are executed before the next event if
+  // the posted task queue is empty.
+  // MessageLoop doesn't make strong guarantees that it is the case, but the
+  // current implementation ensures it and the tests below rely on it.
+  // If changes cause this test to fail, it is reasonable to change it, but
+  // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be
+  // changed accordingly, otherwise they can become flaky.
+  injector()->AddEventAsTask(0, Bind(&DoNothing));
+  Closure check_task =
+      Bind(&ExpectProcessedEvents, Unretained(injector()), 2);
+  Closure posted_task =
+      Bind(&PostMessageLoopTask, FROM_HERE, check_task);
+  injector()->AddEventAsTask(0, posted_task);
+  injector()->AddEventAsTask(0, Bind(&DoNothing));
+  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+  loop()->Run();
+  EXPECT_EQ(4, injector()->processed_events());
+
+  injector()->Reset();
+  injector()->AddEventAsTask(0, Bind(&DoNothing));
+  check_task =
+      Bind(&ExpectProcessedEvents, Unretained(injector()), 2);
+  posted_task = Bind(&PostMessageLoopTask, FROM_HERE, check_task);
+  injector()->AddEventAsTask(0, posted_task);
+  injector()->AddEventAsTask(10, Bind(&DoNothing));
+  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+  loop()->Run();
+  EXPECT_EQ(4, injector()->processed_events());
+}
+
+TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) {
+  int task_count = 0;
+  // Tests that we process tasks while waiting for new events.
+  // The event queue is empty at first.
+  for (int i = 0; i < 10; ++i) {
+    loop()->PostTask(FROM_HERE, Bind(&IncrementInt, &task_count));
+  }
+  // After all the previous tasks have executed, enqueue an event that will
+  // quit.
+  loop()->PostTask(
+      FROM_HERE,
+      Bind(&EventInjector::AddEvent, Unretained(injector()), 0,
+                 MessageLoop::QuitWhenIdleClosure()));
+  loop()->Run();
+  ASSERT_EQ(10, task_count);
+  EXPECT_EQ(1, injector()->processed_events());
+
+  // Tests that we process delayed tasks while waiting for new events.
+  injector()->Reset();
+  task_count = 0;
+  for (int i = 0; i < 10; ++i) {
+    loop()->PostDelayedTask(
+        FROM_HERE,
+        Bind(&IncrementInt, &task_count),
+        TimeDelta::FromMilliseconds(10*i));
+  }
+  // After all the previous tasks have executed, enqueue an event that will
+  // quit.
+  // This relies on the fact that delayed tasks are executed in delay order.
+  // That is verified in message_loop_unittest.cc.
+  loop()->PostDelayedTask(
+      FROM_HERE,
+      Bind(&EventInjector::AddEvent, Unretained(injector()), 10,
+                 MessageLoop::QuitWhenIdleClosure()),
+      TimeDelta::FromMilliseconds(150));
+  loop()->Run();
+  ASSERT_EQ(10, task_count);
+  EXPECT_EQ(1, injector()->processed_events());
+}
+
+TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) {
+  // Tests that we process events while waiting for work.
+  // The event queue is empty at first.
+  for (int i = 0; i < 10; ++i) {
+    injector()->AddDummyEvent(0);
+  }
+  // After all the events have been processed, post a task that will check that
+  // the events have been processed (note: the task executes after the event
+  // that posted it has been handled, so we expect 11 at that point).
+  Closure check_task =
+      Bind(&ExpectProcessedEvents, Unretained(injector()), 11);
+  Closure posted_task =
+      Bind(&PostMessageLoopTask, FROM_HERE, check_task);
+  injector()->AddEventAsTask(10, posted_task);
+
+  // And then quit (relies on the condition tested by TestEventTaskInterleave).
+  injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure());
+  loop()->Run();
+
+  EXPECT_EQ(12, injector()->processed_events());
+}
+
+namespace {
+
+// This class is a helper for the concurrent events / posted tasks test below.
+// It will quit the main loop once enough tasks and events have been processed,
+// while making sure there is always work to do and events in the queue.
+class ConcurrentHelper : public RefCounted<ConcurrentHelper>  {
+ public:
+  explicit ConcurrentHelper(EventInjector* injector)
+      : injector_(injector),
+        event_count_(kStartingEventCount),
+        task_count_(kStartingTaskCount) {
+  }
+
+  void FromTask() {
+    if (task_count_ > 0) {
+      --task_count_;
+    }
+    if (task_count_ == 0 && event_count_ == 0) {
+        MessageLoop::current()->QuitWhenIdle();
+    } else {
+      MessageLoop::current()->PostTask(
+          FROM_HERE, Bind(&ConcurrentHelper::FromTask, this));
+    }
+  }
+
+  void FromEvent() {
+    if (event_count_ > 0) {
+      --event_count_;
+    }
+    if (task_count_ == 0 && event_count_ == 0) {
+        MessageLoop::current()->QuitWhenIdle();
+    } else {
+      injector_->AddEventAsTask(
+          0, Bind(&ConcurrentHelper::FromEvent, this));
+    }
+  }
+
+  int event_count() const { return event_count_; }
+  int task_count() const { return task_count_; }
+
+ private:
+  friend class RefCounted<ConcurrentHelper>;
+
+  ~ConcurrentHelper() {}
+
+  static const int kStartingEventCount = 20;
+  static const int kStartingTaskCount = 20;
+
+  EventInjector* injector_;
+  int event_count_;
+  int task_count_;
+};
+
+}  // namespace
+
+TEST_F(MessagePumpGLibTest, TestConcurrentEventPostedTask) {
+  // Tests that posted tasks don't starve events, nor the opposite.
+  // We use the helper class above. We keep both event and posted task queues
+  // full, the helper verifies that both tasks and events get processed.
+  // If that is not the case, either event_count_ or task_count_ will not get
+  // to 0, and MessageLoop::QuitWhenIdle() will never be called.
+  scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector());
+
+  // Add 2 events to the queue to make sure it is always full (when we remove
+  // the event before processing it).
+  injector()->AddEventAsTask(
+      0, Bind(&ConcurrentHelper::FromEvent, helper.get()));
+  injector()->AddEventAsTask(
+      0, Bind(&ConcurrentHelper::FromEvent, helper.get()));
+
+  // Similarly post 2 tasks.
+  loop()->PostTask(
+      FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get()));
+  loop()->PostTask(
+      FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get()));
+
+  loop()->Run();
+  EXPECT_EQ(0, helper->event_count());
+  EXPECT_EQ(0, helper->task_count());
+}
+
+namespace {
+
+void AddEventsAndDrainGLib(EventInjector* injector) {
+  // Add a couple of dummy events
+  injector->AddDummyEvent(0);
+  injector->AddDummyEvent(0);
+  // Then add an event that will quit the main loop.
+  injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+
+  // Post a couple of dummy tasks
+  MessageLoop::current()->PostTask(FROM_HERE, Bind(&DoNothing));
+  MessageLoop::current()->PostTask(FROM_HERE, Bind(&DoNothing));
+
+  // Drain the events
+  while (g_main_context_pending(NULL)) {
+    g_main_context_iteration(NULL, FALSE);
+  }
+}
+
+}  // namespace
+
+TEST_F(MessagePumpGLibTest, TestDrainingGLib) {
+  // Tests that draining events using GLib works.
+  loop()->PostTask(
+      FROM_HERE,
+      Bind(&AddEventsAndDrainGLib, Unretained(injector())));
+  loop()->Run();
+
+  EXPECT_EQ(3, injector()->processed_events());
+}
+
+
+namespace {
+
+#if defined(TOOLKIT_GTK)
+void AddEventsAndDrainGtk(EventInjector* injector) {
+  // Add a couple of dummy events
+  injector->AddDummyEvent(0);
+  injector->AddDummyEvent(0);
+  // Then add an event that will quit the main loop.
+  injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+
+  // Post a couple of dummy tasks
+  MessageLoop::current()->PostTask(FROM_HERE, Bind(&DoNothing));
+  MessageLoop::current()->PostTask(FROM_HERE, Bind(&DoNothing));
+
+  // Drain the events
+  while (gtk_events_pending()) {
+    gtk_main_iteration();
+  }
+}
+#endif
+
+}  // namespace
+
+#if defined(TOOLKIT_GTK)
+TEST_F(MessagePumpGLibTest, TestDrainingGtk) {
+  // Tests that draining events using Gtk works.
+  loop()->PostTask(
+      FROM_HERE,
+      Bind(&AddEventsAndDrainGtk, Unretained(injector())));
+  loop()->Run();
+
+  EXPECT_EQ(3, injector()->processed_events());
+}
+#endif
+
+namespace {
+
+// Helper class that lets us run the GLib message loop.
+class GLibLoopRunner : public RefCounted<GLibLoopRunner> {
+ public:
+  GLibLoopRunner() : quit_(false) { }
+
+  void RunGLib() {
+    while (!quit_) {
+      g_main_context_iteration(NULL, TRUE);
+    }
+  }
+
+  void RunLoop() {
+#if defined(TOOLKIT_GTK)
+    while (!quit_) {
+      gtk_main_iteration();
+    }
+#else
+    while (!quit_) {
+      g_main_context_iteration(NULL, TRUE);
+    }
+#endif
+  }
+
+  void Quit() {
+    quit_ = true;
+  }
+
+  void Reset() {
+    quit_ = false;
+  }
+
+ private:
+  friend class RefCounted<GLibLoopRunner>;
+
+  ~GLibLoopRunner() {}
+
+  bool quit_;
+};
+
+void TestGLibLoopInternal(EventInjector* injector) {
+  // Allow tasks to be processed from 'native' event loops.
+  MessageLoop::current()->SetNestableTasksAllowed(true);
+  scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
+
+  int task_count = 0;
+  // Add a couple of dummy events
+  injector->AddDummyEvent(0);
+  injector->AddDummyEvent(0);
+  // Post a couple of dummy tasks
+  MessageLoop::current()->PostTask(
+      FROM_HERE, Bind(&IncrementInt, &task_count));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, Bind(&IncrementInt, &task_count));
+  // Delayed events
+  injector->AddDummyEvent(10);
+  injector->AddDummyEvent(10);
+  // Delayed work
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      Bind(&IncrementInt, &task_count),
+      TimeDelta::FromMilliseconds(30));
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      Bind(&GLibLoopRunner::Quit, runner.get()),
+      TimeDelta::FromMilliseconds(40));
+
+  // Run a nested, straight GLib message loop.
+  runner->RunGLib();
+
+  ASSERT_EQ(3, task_count);
+  EXPECT_EQ(4, injector->processed_events());
+  MessageLoop::current()->QuitWhenIdle();
+}
+
+void TestGtkLoopInternal(EventInjector* injector) {
+  // Allow tasks to be processed from 'native' event loops.
+  MessageLoop::current()->SetNestableTasksAllowed(true);
+  scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
+
+  int task_count = 0;
+  // Add a couple of dummy events
+  injector->AddDummyEvent(0);
+  injector->AddDummyEvent(0);
+  // Post a couple of dummy tasks
+  MessageLoop::current()->PostTask(
+      FROM_HERE, Bind(&IncrementInt, &task_count));
+  MessageLoop::current()->PostTask(
+      FROM_HERE, Bind(&IncrementInt, &task_count));
+  // Delayed events
+  injector->AddDummyEvent(10);
+  injector->AddDummyEvent(10);
+  // Delayed work
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      Bind(&IncrementInt, &task_count),
+      TimeDelta::FromMilliseconds(30));
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      Bind(&GLibLoopRunner::Quit, runner.get()),
+      TimeDelta::FromMilliseconds(40));
+
+  // Run a nested, straight Gtk message loop.
+  runner->RunLoop();
+
+  ASSERT_EQ(3, task_count);
+  EXPECT_EQ(4, injector->processed_events());
+  MessageLoop::current()->QuitWhenIdle();
+}
+
+}  // namespace
+
+TEST_F(MessagePumpGLibTest, TestGLibLoop) {
+  // Tests that events and posted tasks are correctly executed if the message
+  // loop is not run by MessageLoop::Run() but by a straight GLib loop.
+  // Note that in this case we don't make strong guarantees about niceness
+  // between events and posted tasks.
+  loop()->PostTask(
+      FROM_HERE,
+      Bind(&TestGLibLoopInternal, Unretained(injector())));
+  loop()->Run();
+}
+
+TEST_F(MessagePumpGLibTest, TestGtkLoop) {
+  // Tests that events and posted tasks are correctly executed if the message
+  // loop is not run by MessageLoop::Run() but by a straight Gtk loop.
+  // Note that in this case we don't make strong guarantees about niceness
+  // between events and posted tasks.
+  loop()->PostTask(
+      FROM_HERE,
+      Bind(&TestGtkLoopInternal, Unretained(injector())));
+  loop()->Run();
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_gtk.cc b/base/message_loop/message_pump_gtk.cc
new file mode 100644
index 0000000..8fa8cf2
--- /dev/null
+++ b/base/message_loop/message_pump_gtk.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_gtk.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "base/debug/trace_event.h"
+#include "base/profiler/scoped_profile.h"
+
+namespace base {
+
+namespace {
+
+const char* EventToTypeString(const GdkEvent* event) {
+  switch (event->type) {
+    case GDK_NOTHING:           return "GDK_NOTHING";
+    case GDK_DELETE:            return "GDK_DELETE";
+    case GDK_DESTROY:           return "GDK_DESTROY";
+    case GDK_EXPOSE:            return "GDK_EXPOSE";
+    case GDK_MOTION_NOTIFY:     return "GDK_MOTION_NOTIFY";
+    case GDK_BUTTON_PRESS:      return "GDK_BUTTON_PRESS";
+    case GDK_2BUTTON_PRESS:     return "GDK_2BUTTON_PRESS";
+    case GDK_3BUTTON_PRESS:     return "GDK_3BUTTON_PRESS";
+    case GDK_BUTTON_RELEASE:    return "GDK_BUTTON_RELEASE";
+    case GDK_KEY_PRESS:         return "GDK_KEY_PRESS";
+    case GDK_KEY_RELEASE:       return "GDK_KEY_RELEASE";
+    case GDK_ENTER_NOTIFY:      return "GDK_ENTER_NOTIFY";
+    case GDK_LEAVE_NOTIFY:      return "GDK_LEAVE_NOTIFY";
+    case GDK_FOCUS_CHANGE:      return "GDK_FOCUS_CHANGE";
+    case GDK_CONFIGURE:         return "GDK_CONFIGURE";
+    case GDK_MAP:               return "GDK_MAP";
+    case GDK_UNMAP:             return "GDK_UNMAP";
+    case GDK_PROPERTY_NOTIFY:   return "GDK_PROPERTY_NOTIFY";
+    case GDK_SELECTION_CLEAR:   return "GDK_SELECTION_CLEAR";
+    case GDK_SELECTION_REQUEST: return "GDK_SELECTION_REQUEST";
+    case GDK_SELECTION_NOTIFY:  return "GDK_SELECTION_NOTIFY";
+    case GDK_PROXIMITY_IN:      return "GDK_PROXIMITY_IN";
+    case GDK_PROXIMITY_OUT:     return "GDK_PROXIMITY_OUT";
+    case GDK_DRAG_ENTER:        return "GDK_DRAG_ENTER";
+    case GDK_DRAG_LEAVE:        return "GDK_DRAG_LEAVE";
+    case GDK_DRAG_MOTION:       return "GDK_DRAG_MOTION";
+    case GDK_DRAG_STATUS:       return "GDK_DRAG_STATUS";
+    case GDK_DROP_START:        return "GDK_DROP_START";
+    case GDK_DROP_FINISHED:     return "GDK_DROP_FINISHED";
+    case GDK_CLIENT_EVENT:      return "GDK_CLIENT_EVENT";
+    case GDK_VISIBILITY_NOTIFY: return "GDK_VISIBILITY_NOTIFY";
+    case GDK_NO_EXPOSE:         return "GDK_NO_EXPOSE";
+    case GDK_SCROLL:            return "GDK_SCROLL";
+    case GDK_WINDOW_STATE:      return "GDK_WINDOW_STATE";
+    case GDK_SETTING:           return "GDK_SETTING";
+    case GDK_OWNER_CHANGE:      return "GDK_OWNER_CHANGE";
+    case GDK_GRAB_BROKEN:       return "GDK_GRAB_BROKEN";
+    case GDK_DAMAGE:            return "GDK_DAMAGE";
+    default:
+      return "Unknown Gdk Event";
+  }
+}
+
+}  // namespace
+
+MessagePumpGtk::MessagePumpGtk() : MessagePumpGlib() {
+  gdk_event_handler_set(&EventDispatcher, this, NULL);
+}
+
+void MessagePumpGtk::DispatchEvents(GdkEvent* event) {
+  UNSHIPPED_TRACE_EVENT1("task", "MessagePumpGtk::DispatchEvents",
+                         "type", EventToTypeString(event));
+
+  WillProcessEvent(event);
+
+  MessagePumpDispatcher* dispatcher = GetDispatcher();
+  if (!dispatcher)
+    gtk_main_do_event(event);
+  else if (!dispatcher->Dispatch(event))
+    Quit();
+
+  DidProcessEvent(event);
+}
+
+// static
+Display* MessagePumpGtk::GetDefaultXDisplay() {
+  static GdkDisplay* display = gdk_display_get_default();
+  if (!display) {
+    // GTK / GDK has not been initialized, which is a decision we wish to
+    // support, for example for the GPU process.
+    static Display* xdisplay = XOpenDisplay(NULL);
+    return xdisplay;
+  }
+  return GDK_DISPLAY_XDISPLAY(display);
+}
+
+MessagePumpGtk::~MessagePumpGtk() {
+  gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event),
+                        this, NULL);
+}
+
+void MessagePumpGtk::WillProcessEvent(GdkEvent* event) {
+  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), WillProcessEvent(event));
+}
+
+void MessagePumpGtk::DidProcessEvent(GdkEvent* event) {
+  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(event));
+}
+
+// static
+void MessagePumpGtk::EventDispatcher(GdkEvent* event, gpointer data) {
+  MessagePumpGtk* message_pump = reinterpret_cast<MessagePumpGtk*>(data);
+  message_pump->DispatchEvents(event);
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_gtk.h b/base/message_loop/message_pump_gtk.h
new file mode 100644
index 0000000..e22e04f
--- /dev/null
+++ b/base/message_loop/message_pump_gtk.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_GTK_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_GTK_H_
+
+#include "base/message_loop/message_pump_glib.h"
+
+typedef union _GdkEvent GdkEvent;
+typedef struct _XDisplay Display;
+
+namespace base {
+
+// The documentation for this class is in message_pump_glib.h
+class MessagePumpObserver {
+ public:
+  // This method is called before processing a message.
+  virtual void WillProcessEvent(GdkEvent* event) = 0;
+
+  // This method is called after processing a message.
+  virtual void DidProcessEvent(GdkEvent* event) = 0;
+
+ protected:
+  virtual ~MessagePumpObserver() {}
+};
+
+// The documentation for this class is in message_pump_glib.h
+//
+// The nested loop is exited by either posting a quit, or returning false
+// from Dispatch.
+class MessagePumpDispatcher {
+ public:
+  // Dispatches the event. If true is returned processing continues as
+  // normal. If false is returned, the nested loop exits immediately.
+  virtual bool Dispatch(GdkEvent* event) = 0;
+
+ protected:
+  virtual ~MessagePumpDispatcher() {}
+};
+
+// This class implements a message-pump for dispatching GTK events.
+class BASE_EXPORT MessagePumpGtk : public MessagePumpGlib {
+ public:
+  MessagePumpGtk();
+
+  // Dispatch an available GdkEvent. Essentially this allows a subclass to do
+  // some task before/after calling the default handler (EventDispatcher).
+  void DispatchEvents(GdkEvent* event);
+
+  // Returns default X Display.
+  static Display* GetDefaultXDisplay();
+
+ protected:
+  virtual ~MessagePumpGtk();
+
+ private:
+  // Invoked from EventDispatcher. Notifies all observers we're about to
+  // process an event.
+  void WillProcessEvent(GdkEvent* event);
+
+  // Invoked from EventDispatcher. Notifies all observers we processed an
+  // event.
+  void DidProcessEvent(GdkEvent* event);
+
+  // Callback prior to gdk dispatching an event.
+  static void EventDispatcher(GdkEvent* event, void* data);
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpGtk);
+};
+
+typedef MessagePumpGtk MessagePumpForUI;
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_GTK_H_
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc
new file mode 100644
index 0000000..8de0db2
--- /dev/null
+++ b/base/message_loop/message_pump_libevent.cc
@@ -0,0 +1,375 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_libevent.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "base/auto_reset.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/time.h"
+#include "third_party/libevent/event.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+
+// Lifecycle of struct event
+// Libevent uses two main data structures:
+// struct event_base (of which there is one per message pump), and
+// struct event (of which there is roughly one per socket).
+// The socket's struct event is created in
+// MessagePumpLibevent::WatchFileDescriptor(),
+// is owned by the FileDescriptorWatcher, and is destroyed in
+// StopWatchingFileDescriptor().
+// It is moved into and out of lists in struct event_base by
+// the libevent functions event_add() and event_del().
+//
+// TODO(dkegel):
+// At the moment bad things happen if a FileDescriptorWatcher
+// is active after its MessagePumpLibevent has been destroyed.
+// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
+// Not clear yet whether that situation occurs in practice,
+// but if it does, we need to fix it.
+
+namespace base {
+
+// Return 0 on success
+// Too small a function to bother putting in a library?
+static int SetNonBlocking(int fd) {
+  int flags = fcntl(fd, F_GETFL, 0);
+  if (flags == -1)
+    flags = 0;
+  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+}
+
+MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
+    : event_(NULL),
+      pump_(NULL),
+      watcher_(NULL),
+      weak_factory_(this) {
+}
+
+MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
+  if (event_) {
+    StopWatchingFileDescriptor();
+  }
+}
+
+bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
+  event* e = ReleaseEvent();
+  if (e == NULL)
+    return true;
+
+  // event_del() is a no-op if the event isn't active.
+  int rv = event_del(e);
+  delete e;
+  pump_ = NULL;
+  watcher_ = NULL;
+  return (rv == 0);
+}
+
+void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e) {
+  DCHECK(e);
+  DCHECK(!event_);
+
+  event_ = e;
+}
+
+event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
+  struct event *e = event_;
+  event_ = NULL;
+  return e;
+}
+
+void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
+    int fd, MessagePumpLibevent* pump) {
+  // Since OnFileCanWriteWithoutBlocking() gets called first, it can stop
+  // watching the file descriptor.
+  if (!watcher_)
+    return;
+  pump->WillProcessIOEvent();
+  watcher_->OnFileCanReadWithoutBlocking(fd);
+  pump->DidProcessIOEvent();
+}
+
+void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
+    int fd, MessagePumpLibevent* pump) {
+  DCHECK(watcher_);
+  pump->WillProcessIOEvent();
+  watcher_->OnFileCanWriteWithoutBlocking(fd);
+  pump->DidProcessIOEvent();
+}
+
+MessagePumpLibevent::MessagePumpLibevent()
+    : keep_running_(true),
+      in_run_(false),
+      processed_io_events_(false),
+      event_base_(event_base_new()),
+      wakeup_pipe_in_(-1),
+      wakeup_pipe_out_(-1) {
+  if (!Init())
+     NOTREACHED();
+}
+
+MessagePumpLibevent::~MessagePumpLibevent() {
+  DCHECK(wakeup_event_);
+  DCHECK(event_base_);
+  event_del(wakeup_event_);
+  delete wakeup_event_;
+  if (wakeup_pipe_in_ >= 0) {
+    if (HANDLE_EINTR(close(wakeup_pipe_in_)) < 0)
+      DPLOG(ERROR) << "close";
+  }
+  if (wakeup_pipe_out_ >= 0) {
+    if (HANDLE_EINTR(close(wakeup_pipe_out_)) < 0)
+      DPLOG(ERROR) << "close";
+  }
+  event_base_free(event_base_);
+}
+
+bool MessagePumpLibevent::WatchFileDescriptor(int fd,
+                                              bool persistent,
+                                              int mode,
+                                              FileDescriptorWatcher *controller,
+                                              Watcher *delegate) {
+  DCHECK_GE(fd, 0);
+  DCHECK(controller);
+  DCHECK(delegate);
+  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
+  // WatchFileDescriptor should be called on the pump thread. It is not
+  // threadsafe, and your watcher may never be registered.
+  DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
+
+  int event_mask = persistent ? EV_PERSIST : 0;
+  if (mode & WATCH_READ) {
+    event_mask |= EV_READ;
+  }
+  if (mode & WATCH_WRITE) {
+    event_mask |= EV_WRITE;
+  }
+
+  scoped_ptr<event> evt(controller->ReleaseEvent());
+  if (evt.get() == NULL) {
+    // Ownership is transferred to the controller.
+    evt.reset(new event);
+  } else {
+    // Make sure we don't pick up any funky internal libevent masks.
+    int old_interest_mask = evt.get()->ev_events &
+        (EV_READ | EV_WRITE | EV_PERSIST);
+
+    // Combine old/new event masks.
+    event_mask |= old_interest_mask;
+
+    // Must disarm the event before we can reuse it.
+    event_del(evt.get());
+
+    // It's illegal to use this function to listen on 2 separate fds with the
+    // same |controller|.
+    if (EVENT_FD(evt.get()) != fd) {
+      NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd;
+      return false;
+    }
+  }
+
+  // Set current interest mask and message pump for this event.
+  event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller);
+
+  // Tell libevent which message pump this socket will belong to when we add it.
+  if (event_base_set(event_base_, evt.get())) {
+    return false;
+  }
+
+  // Add this socket to the list of monitored sockets.
+  if (event_add(evt.get(), NULL)) {
+    return false;
+  }
+
+  // Transfer ownership of evt to controller.
+  controller->Init(evt.release());
+
+  controller->set_watcher(delegate);
+  controller->set_pump(this);
+
+  return true;
+}
+
+void MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
+  io_observers_.AddObserver(obs);
+}
+
+void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
+  io_observers_.RemoveObserver(obs);
+}
+
+// Tell libevent to break out of inner loop.
+static void timer_callback(int fd, short events, void *context)
+{
+  event_base_loopbreak((struct event_base *)context);
+}
+
+// Reentrant!
+void MessagePumpLibevent::Run(Delegate* delegate) {
+  DCHECK(keep_running_) << "Quit must have been called outside of Run!";
+  AutoReset<bool> auto_reset_in_run(&in_run_, true);
+
+  // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641.
+  // Instead, make our own timer and reuse it on each call to event_base_loop().
+  scoped_ptr<event> timer_event(new event);
+
+  for (;;) {
+#if defined(OS_MACOSX)
+    mac::ScopedNSAutoreleasePool autorelease_pool;
+#endif
+
+    bool did_work = delegate->DoWork();
+    if (!keep_running_)
+      break;
+
+    event_base_loop(event_base_, EVLOOP_NONBLOCK);
+    did_work |= processed_io_events_;
+    processed_io_events_ = false;
+    if (!keep_running_)
+      break;
+
+    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    did_work = delegate->DoIdleWork();
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    // EVLOOP_ONCE tells libevent to only block once,
+    // but to service all pending events when it wakes up.
+    if (delayed_work_time_.is_null()) {
+      event_base_loop(event_base_, EVLOOP_ONCE);
+    } else {
+      TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
+      if (delay > TimeDelta()) {
+        struct timeval poll_tv;
+        poll_tv.tv_sec = delay.InSeconds();
+        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
+        event_set(timer_event.get(), -1, 0, timer_callback, event_base_);
+        event_base_set(event_base_, timer_event.get());
+        event_add(timer_event.get(), &poll_tv);
+        event_base_loop(event_base_, EVLOOP_ONCE);
+        event_del(timer_event.get());
+      } else {
+        // It looks like delayed_work_time_ indicates a time in the past, so we
+        // need to call DoDelayedWork now.
+        delayed_work_time_ = TimeTicks();
+      }
+    }
+  }
+
+  keep_running_ = true;
+}
+
+void MessagePumpLibevent::Quit() {
+  DCHECK(in_run_);
+  // Tell both libevent and Run that they should break out of their loops.
+  keep_running_ = false;
+  ScheduleWork();
+}
+
+void MessagePumpLibevent::ScheduleWork() {
+  // Tell libevent (in a threadsafe way) that it should break out of its loop.
+  char buf = 0;
+  int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1));
+  DCHECK(nwrite == 1 || errno == EAGAIN)
+      << "[nwrite:" << nwrite << "] [errno:" << errno << "]";
+}
+
+void MessagePumpLibevent::ScheduleDelayedWork(
+    const TimeTicks& delayed_work_time) {
+  // We know that we can't be blocked on Wait right now since this method can
+  // only be called on the same thread as Run, so we only need to update our
+  // record of how long to sleep when we do sleep.
+  delayed_work_time_ = delayed_work_time;
+}
+
+void MessagePumpLibevent::WillProcessIOEvent() {
+  FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
+}
+
+void MessagePumpLibevent::DidProcessIOEvent() {
+  FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
+}
+
+bool MessagePumpLibevent::Init() {
+  int fds[2];
+  if (pipe(fds)) {
+    DLOG(ERROR) << "pipe() failed, errno: " << errno;
+    return false;
+  }
+  if (SetNonBlocking(fds[0])) {
+    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
+    return false;
+  }
+  if (SetNonBlocking(fds[1])) {
+    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
+    return false;
+  }
+  wakeup_pipe_out_ = fds[0];
+  wakeup_pipe_in_ = fds[1];
+
+  wakeup_event_ = new event;
+  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
+            OnWakeup, this);
+  event_base_set(event_base_, wakeup_event_);
+
+  if (event_add(wakeup_event_, 0))
+    return false;
+  return true;
+}
+
+// static
+void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
+                                                 void* context) {
+  WeakPtr<FileDescriptorWatcher> controller =
+      static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr();
+  DCHECK(controller.get());
+
+  MessagePumpLibevent* pump = controller->pump();
+  pump->processed_io_events_ = true;
+
+  if (flags & EV_WRITE) {
+    controller->OnFileCanWriteWithoutBlocking(fd, pump);
+  }
+  // Check |controller| in case it's been deleted in
+  // controller->OnFileCanWriteWithoutBlocking().
+  if (controller.get() && flags & EV_READ) {
+    controller->OnFileCanReadWithoutBlocking(fd, pump);
+  }
+}
+
+// Called if a byte is received on the wakeup pipe.
+// static
+void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
+  MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context);
+  DCHECK(that->wakeup_pipe_out_ == socket);
+
+  // Remove and discard the wakeup byte.
+  char buf;
+  int nread = HANDLE_EINTR(read(socket, &buf, 1));
+  DCHECK_EQ(nread, 1);
+  that->processed_io_events_ = true;
+  // Tell libevent to break out of inner loop.
+  event_base_loopbreak(that->event_base_);
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_libevent.h b/base/message_loop/message_pump_libevent.h
new file mode 100644
index 0000000..a54ef88
--- /dev/null
+++ b/base/message_loop/message_pump_libevent.h
@@ -0,0 +1,179 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_pump.h"
+#include "base/observer_list.h"
+#include "base/threading/thread_checker.h"
+#include "base/time.h"
+
+// Declare structs we need from libevent.h rather than including it
+struct event_base;
+struct event;
+
+namespace base {
+
+// Class to monitor sockets and issue callbacks when sockets are ready for I/O
+// TODO(dkegel): add support for background file IO somehow
+class BASE_EXPORT MessagePumpLibevent : public MessagePump {
+ public:
+  class IOObserver {
+   public:
+    IOObserver() {}
+
+    // An IOObserver is an object that receives IO notifications from the
+    // MessagePump.
+    //
+    // NOTE: An IOObserver implementation should be extremely fast!
+    virtual void WillProcessIOEvent() = 0;
+    virtual void DidProcessIOEvent() = 0;
+
+   protected:
+    virtual ~IOObserver() {}
+  };
+
+  // Used with WatchFileDescriptor to asynchronously monitor the I/O readiness
+  // of a file descriptor.
+  class Watcher {
+   public:
+    // Called from MessageLoop::Run when an FD can be read from/written to
+    // without blocking
+    virtual void OnFileCanReadWithoutBlocking(int fd) = 0;
+    virtual void OnFileCanWriteWithoutBlocking(int fd) = 0;
+
+   protected:
+    virtual ~Watcher() {}
+  };
+
+  // Object returned by WatchFileDescriptor to manage further watching.
+  class FileDescriptorWatcher {
+   public:
+    FileDescriptorWatcher();
+    ~FileDescriptorWatcher();  // Implicitly calls StopWatchingFileDescriptor.
+
+    // NOTE: These methods aren't called StartWatching()/StopWatching() to
+    // avoid confusion with the win32 ObjectWatcher class.
+
+    // Stop watching the FD, always safe to call.  No-op if there's nothing
+    // to do.
+    bool StopWatchingFileDescriptor();
+
+   private:
+    friend class MessagePumpLibevent;
+    friend class MessagePumpLibeventTest;
+
+    // Called by MessagePumpLibevent, ownership of |e| is transferred to this
+    // object.
+    void Init(event* e);
+
+    // Used by MessagePumpLibevent to take ownership of event_.
+    event* ReleaseEvent();
+
+    void set_pump(MessagePumpLibevent* pump) { pump_ = pump; }
+    MessagePumpLibevent* pump() const { return pump_; }
+
+    void set_watcher(Watcher* watcher) { watcher_ = watcher; }
+
+    void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump);
+    void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump);
+
+    event* event_;
+    MessagePumpLibevent* pump_;
+    Watcher* watcher_;
+    WeakPtrFactory<FileDescriptorWatcher> weak_factory_;
+
+    DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher);
+  };
+
+  enum Mode {
+    WATCH_READ = 1 << 0,
+    WATCH_WRITE = 1 << 1,
+    WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE
+  };
+
+  MessagePumpLibevent();
+
+  // Have the current thread's message loop watch for a a situation in which
+  // reading/writing to the FD can be performed without blocking.
+  // Callers must provide a preallocated FileDescriptorWatcher object which
+  // can later be used to manage the lifetime of this event.
+  // If a FileDescriptorWatcher is passed in which is already attached to
+  // an event, then the effect is cumulative i.e. after the call |controller|
+  // will watch both the previous event and the new one.
+  // If an error occurs while calling this method in a cumulative fashion, the
+  // event previously attached to |controller| is aborted.
+  // Returns true on success.
+  // Must be called on the same thread the message_pump is running on.
+  // TODO(dkegel): switch to edge-triggered readiness notification
+  bool WatchFileDescriptor(int fd,
+                           bool persistent,
+                           int mode,
+                           FileDescriptorWatcher *controller,
+                           Watcher *delegate);
+
+  void AddIOObserver(IOObserver* obs);
+  void RemoveIOObserver(IOObserver* obs);
+
+  // MessagePump methods:
+  virtual void Run(Delegate* delegate) OVERRIDE;
+  virtual void Quit() OVERRIDE;
+  virtual void ScheduleWork() OVERRIDE;
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+
+ protected:
+  virtual ~MessagePumpLibevent();
+
+ private:
+  friend class MessagePumpLibeventTest;
+
+  void WillProcessIOEvent();
+  void DidProcessIOEvent();
+
+  // Risky part of constructor.  Returns true on success.
+  bool Init();
+
+  // Called by libevent to tell us a registered FD can be read/written to.
+  static void OnLibeventNotification(int fd, short flags,
+                                     void* context);
+
+  // Unix pipe used to implement ScheduleWork()
+  // ... callback; called by libevent inside Run() when pipe is ready to read
+  static void OnWakeup(int socket, short flags, void* context);
+
+  // This flag is set to false when Run should return.
+  bool keep_running_;
+
+  // This flag is set when inside Run.
+  bool in_run_;
+
+  // This flag is set if libevent has processed I/O events.
+  bool processed_io_events_;
+
+  // The time at which we should call DoDelayedWork.
+  TimeTicks delayed_work_time_;
+
+  // Libevent dispatcher.  Watches all sockets registered with it, and sends
+  // readiness callbacks when a socket is ready for I/O.
+  event_base* event_base_;
+
+  // ... write end; ScheduleWork() writes a single byte to it
+  int wakeup_pipe_in_;
+  // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
+  int wakeup_pipe_out_;
+  // ... libevent wrapper for read end
+  event* wakeup_event_;
+
+  ObserverList<IOObserver> io_observers_;
+  ThreadChecker watch_file_descriptor_caller_checker_;
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent);
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc
new file mode 100644
index 0000000..657ac7d
--- /dev/null
+++ b/base/message_loop/message_pump_libevent_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_libevent.h"
+
+#include <unistd.h>
+
+#include "base/message_loop/message_loop.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libevent/event.h"
+
+namespace base {
+
+class MessagePumpLibeventTest : public testing::Test {
+ protected:
+  MessagePumpLibeventTest()
+      : ui_loop_(MessageLoop::TYPE_UI),
+        io_thread_("MessagePumpLibeventTestIOThread") {}
+  virtual ~MessagePumpLibeventTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    Thread::Options options(MessageLoop::TYPE_IO, 0);
+    ASSERT_TRUE(io_thread_.StartWithOptions(options));
+    ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
+    int ret = pipe(pipefds_);
+    ASSERT_EQ(0, ret);
+  }
+
+  virtual void TearDown() OVERRIDE {
+    if (HANDLE_EINTR(close(pipefds_[0])) < 0)
+      PLOG(ERROR) << "close";
+    if (HANDLE_EINTR(close(pipefds_[1])) < 0)
+      PLOG(ERROR) << "close";
+  }
+
+  MessageLoop* ui_loop() { return &ui_loop_; }
+  MessageLoopForIO* io_loop() const {
+    return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
+  }
+
+  void OnLibeventNotification(
+      MessagePumpLibevent* pump,
+      MessagePumpLibevent::FileDescriptorWatcher* controller) {
+    pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
+  }
+
+  int pipefds_[2];
+
+ private:
+  MessageLoop ui_loop_;
+  Thread io_thread_;
+};
+
+namespace {
+
+// Concrete implementation of MessagePumpLibevent::Watcher that does
+// nothing useful.
+class StupidWatcher : public MessagePumpLibevent::Watcher {
+ public:
+  virtual ~StupidWatcher() {}
+
+  // base:MessagePumpLibevent::Watcher interface
+  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {}
+  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
+};
+
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+// Test to make sure that we catch calling WatchFileDescriptor off of the
+// wrong thread.
+TEST_F(MessagePumpLibeventTest, TestWatchingFromBadThread) {
+  MessagePumpLibevent::FileDescriptorWatcher watcher;
+  StupidWatcher delegate;
+
+  ASSERT_DEATH(io_loop()->WatchFileDescriptor(
+      STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate),
+      "Check failed: "
+      "watch_file_descriptor_caller_checker_.CalledOnValidThread()");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+class BaseWatcher : public MessagePumpLibevent::Watcher {
+ public:
+  explicit BaseWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller)
+      : controller_(controller) {
+    DCHECK(controller_);
+  }
+  virtual ~BaseWatcher() {}
+
+  // base:MessagePumpLibevent::Watcher interface
+  virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
+    NOTREACHED();
+  }
+
+  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+    NOTREACHED();
+  }
+
+ protected:
+  MessagePumpLibevent::FileDescriptorWatcher* controller_;
+};
+
+class DeleteWatcher : public BaseWatcher {
+ public:
+  explicit DeleteWatcher(
+      MessagePumpLibevent::FileDescriptorWatcher* controller)
+      : BaseWatcher(controller) {}
+
+  virtual ~DeleteWatcher() {
+    DCHECK(!controller_);
+  }
+
+  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+    DCHECK(controller_);
+    delete controller_;
+    controller_ = NULL;
+  }
+};
+
+TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
+  scoped_refptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
+  MessagePumpLibevent::FileDescriptorWatcher* watcher =
+      new MessagePumpLibevent::FileDescriptorWatcher;
+  DeleteWatcher delegate(watcher);
+  pump->WatchFileDescriptor(pipefds_[1],
+      false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
+
+  // Spoof a libevent notification.
+  OnLibeventNotification(pump.get(), watcher);
+}
+
+class StopWatcher : public BaseWatcher {
+ public:
+  explicit StopWatcher(
+      MessagePumpLibevent::FileDescriptorWatcher* controller)
+      : BaseWatcher(controller) {}
+
+  virtual ~StopWatcher() {}
+
+  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+    controller_->StopWatchingFileDescriptor();
+  }
+};
+
+TEST_F(MessagePumpLibeventTest, StopWatcher) {
+  scoped_refptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
+  MessagePumpLibevent::FileDescriptorWatcher watcher;
+  StopWatcher delegate(&watcher);
+  pump->WatchFileDescriptor(pipefds_[1],
+      false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
+
+  // Spoof a libevent notification.
+  OnLibeventNotification(pump.get(), &watcher);
+}
+
+}  // namespace
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_observer.h b/base/message_loop/message_pump_observer.h
new file mode 100644
index 0000000..cb46fa3
--- /dev/null
+++ b/base/message_loop/message_pump_observer.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H
+
+#include "base/base_export.h"
+#include "base/event_types.h"
+
+namespace base {
+
+enum EventStatus {
+  EVENT_CONTINUE,    // The event should be dispatched as normal.
+#if defined(USE_X11)
+  EVENT_HANDLED      // The event should not be processed any farther.
+#endif
+};
+
+// A MessagePumpObserver is an object that receives global
+// notifications from the UI MessageLoop with MessagePumpWin or
+// MessagePumpAuraX11.
+//
+// NOTE: An Observer implementation should be extremely fast!
+//
+// For use with MessagePumpAuraX11, please see message_pump_glib.h for more
+// info about how this is invoked in this environment.
+class BASE_EXPORT MessagePumpObserver {
+ public:
+  // This method is called before processing a NativeEvent. If the
+  // method returns EVENT_HANDLED, it indicates the event has already
+  // been handled, so the event is not processed any farther. If the
+  // method returns EVENT_CONTINUE, the event dispatching proceeds as
+  // normal.
+  virtual EventStatus WillProcessEvent(const NativeEvent& event) = 0;
+
+  // This method is called after processing a message. This method
+  // will not be called if WillProcessEvent returns EVENT_HANDLED.
+  virtual void DidProcessEvent(const NativeEvent& event) = 0;
+
+ protected:
+  virtual ~MessagePumpObserver() {}
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H
diff --git a/base/message_loop/message_pump_ozone.cc b/base/message_loop/message_pump_ozone.cc
new file mode 100644
index 0000000..5c0bf83
--- /dev/null
+++ b/base/message_loop/message_pump_ozone.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_ozone.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+
+namespace base {
+
+MessagePumpOzone::MessagePumpOzone()
+    : MessagePumpLibevent() {
+}
+
+MessagePumpOzone::~MessagePumpOzone() {
+}
+
+void MessagePumpOzone::AddObserver(MessagePumpObserver* /* observer */) {
+  NOTIMPLEMENTED();
+}
+
+void MessagePumpOzone::RemoveObserver(MessagePumpObserver* /* observer */) {
+  NOTIMPLEMENTED();
+}
+
+// static
+MessagePumpOzone* MessagePumpOzone::Current() {
+  MessageLoopForUI* loop = MessageLoopForUI::current();
+  return static_cast<MessagePumpOzone*>(loop->pump_ui());
+}
+
+void MessagePumpOzone::AddDispatcherForRootWindow(
+    MessagePumpDispatcher* dispatcher) {
+  // Only one root window is supported.
+  DCHECK(dispatcher_.size() == 0);
+  dispatcher_.insert(dispatcher_.begin(),dispatcher);
+}
+
+void MessagePumpOzone::RemoveDispatcherForRootWindow(
+      MessagePumpDispatcher* dispatcher) {
+  DCHECK(dispatcher_.size() == 1);
+  dispatcher_.pop_back();
+}
+
+bool MessagePumpOzone::Dispatch(const NativeEvent& dev) {
+  if (dispatcher_.size() > 0)
+    return dispatcher_[0]->Dispatch(dev);
+  else
+    return true;
+}
+
+// This code assumes that the caller tracks the lifetime of the |dispatcher|.
+void MessagePumpOzone::RunWithDispatcher(
+    Delegate* delegate, MessagePumpDispatcher* dispatcher) {
+  dispatcher_.push_back(dispatcher);
+  Run(delegate);
+  dispatcher_.pop_back();
+}
+
+}  // namespace base
diff --git a/base/message_loop/message_pump_ozone.h b/base/message_loop/message_pump_ozone.h
new file mode 100644
index 0000000..de75ab4
--- /dev/null
+++ b/base/message_loop/message_pump_ozone.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_OZONE_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_OZONE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_pump_dispatcher.h"
+#include "base/message_loop/message_pump_libevent.h"
+#include "base/message_loop/message_pump_observer.h"
+#include "base/observer_list.h"
+
+namespace base {
+
+// This class implements a message-pump for processing events from input devices
+// Refer to MessagePump for further documentation.
+class BASE_EXPORT MessagePumpOzone : public MessagePumpLibevent,
+                                     public MessagePumpDispatcher {
+ public:
+  MessagePumpOzone();
+
+  // Returns the UI message pump.
+  static MessagePumpOzone* Current();
+
+  // Add/Remove the root window dispatcher.
+  void AddDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
+  void RemoveDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
+
+  void RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher);
+
+  // Add / remove an Observer, which will start receiving notifications
+  // immediately.
+  void AddObserver(MessagePumpObserver* observer);
+  void RemoveObserver(MessagePumpObserver* observer);
+
+  // Overridden from MessagePumpDispatcher.
+  virtual bool Dispatch(const NativeEvent& event) OVERRIDE;
+
+ private:
+  virtual ~MessagePumpOzone();
+  std::vector<MessagePumpDispatcher*> dispatcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpOzone);
+};
+
+typedef MessagePumpOzone MessagePumpForUI;
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_OZONE_H_