libchromeos: New chromeos::MessageLoop virtual interface.

This patch adds a MessageLoop interface to libchromeos, together with
a fake implementation used for testing and a glib main loop
implementation.

This new interface serves two purposes:
 * It provides a virtual interface that can be mocked or faked for testing.
 * It provides a new functionality to cancel a pending task before it runs,
   something that is not possible in the base message loop.
 * It provides a glib implementation of this interface that can be used by
   daemons calling directly glib main loop in many places, allowing us to
   progresivelly migrate those calls to this interface and then change the
   backend to a different implementation.

This patch includes the basic PostTask and PostDelayedTask methods. I/O
handling methods will be added later.

BUG=brillo:91
TEST=Added unittests.

Change-Id: Ibe62a1f460b2e044a7b515290c441bcac7bd602c
Reviewed-on: https://chromium-review.googlesource.com/276890
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/chromeos/message_loops/message_loop_utils.cc b/chromeos/message_loops/message_loop_utils.cc
new file mode 100644
index 0000000..2096976
--- /dev/null
+++ b/chromeos/message_loops/message_loop_utils.cc
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium OS 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 <chromeos/message_loops/message_loop_utils.h>
+
+#include <chromeos/bind_lambda.h>
+
+namespace chromeos {
+
+void MessageLoopRunUntil(
+    MessageLoop* loop,
+    base::TimeDelta timeout,
+    base::Callback<bool()> terminate) {
+  bool timeout_called = false;
+  MessageLoop::TaskId task_id = loop->PostDelayedTask(
+    base::Bind([&timeout_called]() { timeout_called = true; }),
+    timeout);
+  while (!timeout_called && (terminate.is_null() || !terminate.Run()))
+    loop->RunOnce(true);
+
+  if (!timeout_called)
+    loop->CancelTask(task_id);
+}
+
+int MessageLoopRunMaxIterations(MessageLoop* loop, int iterations) {
+  int result;
+  for (result = 0; result < iterations && loop->RunOnce(false); result++) {}
+  return result;
+}
+
+}  // namespace chromeos