libchromeos: Migrate AsyncEventSequencer to libchromeos

This enables sharing this functionality between peerd and buffet.

BUG=chromium:398626
TEST=libchromeos/buffet unittests

Change-Id: Ic38b9bbf491b57d18b0409f0587efedeab6ef988
Reviewed-on: https://chromium-review.googlesource.com/210402
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/async_event_sequencer.cc b/buffet/async_event_sequencer.cc
deleted file mode 100644
index b90b552..0000000
--- a/buffet/async_event_sequencer.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2014 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 "buffet/async_event_sequencer.h"
-
-namespace buffet {
-
-namespace dbus_utils {
-
-AsyncEventSequencer::AsyncEventSequencer() { }
-AsyncEventSequencer::~AsyncEventSequencer() { }
-
-AsyncEventSequencer::Handler AsyncEventSequencer::GetHandler(
-    const std::string& descriptive_message, bool failure_is_fatal) {
-  CHECK(!started_) << "Cannot create handlers after OnAllTasksCompletedCall()";
-  int unique_registration_id = ++registration_counter_;
-  outstanding_registrations_.insert(unique_registration_id);
-  return base::Bind(&AsyncEventSequencer::HandleFinish, this,
-                    unique_registration_id, descriptive_message,
-                    failure_is_fatal);
-}
-
-AsyncEventSequencer::ExportHandler AsyncEventSequencer::GetExportHandler(
-        const std::string& interface_name, const std::string& method_name,
-        const std::string& descriptive_message, bool failure_is_fatal) {
-  auto finish_handler = GetHandler(descriptive_message, failure_is_fatal);
-  return base::Bind(&AsyncEventSequencer::HandleDBusMethodExported, this,
-                    finish_handler,
-                    interface_name,
-                    method_name);
-}
-
-void AsyncEventSequencer::OnAllTasksCompletedCall(
-    std::vector<CompletionAction> actions) {
-  CHECK(!started_) << "OnAllTasksCompletedCall called twice!";
-  started_ = true;
-  completion_actions_.assign(actions.begin(), actions.end());
-  // All of our callbacks might have been called already.
-  PossiblyRunCompletionActions();
-}
-
-namespace {
-void IgnoreSuccess(const AsyncEventSequencer::CompletionTask& task,
-                   bool /*success*/) { task.Run(); }
-}  // namespace
-
-AsyncEventSequencer::CompletionAction AsyncEventSequencer::WrapCompletionTask(
-    const CompletionTask& task) {
-  return base::Bind(&IgnoreSuccess, task);
-}
-
-void AsyncEventSequencer::HandleFinish(int registration_number,
-                                       const std::string& error_message,
-                                       bool failure_is_fatal, bool success) {
-  RetireRegistration(registration_number);
-  CheckForFailure(failure_is_fatal, success, error_message);
-  PossiblyRunCompletionActions();
-}
-
-void AsyncEventSequencer::HandleDBusMethodExported(
-    const AsyncEventSequencer::Handler& finish_handler,
-    const std::string& expected_interface_name,
-    const std::string& expected_method_name,
-    const std::string& actual_interface_name,
-    const std::string& actual_method_name, bool success) {
-  CHECK_EQ(expected_method_name, actual_method_name)
-      << "Exported DBus method '" << actual_method_name << "' "
-      << "but expected '" << expected_method_name << "'";
-  CHECK_EQ(expected_interface_name, actual_interface_name)
-      << "Exported method DBus interface '" << actual_interface_name << "' "
-      << "but expected '" << expected_interface_name << "'";
-  finish_handler.Run(success);
-}
-
-
-void AsyncEventSequencer::RetireRegistration(int registration_number) {
-  const size_t handlers_retired = outstanding_registrations_.erase(
-      registration_number);
-  CHECK_EQ(1, handlers_retired)
-      << "Tried to retire invalid handler " << registration_number << ")";
-}
-
-void AsyncEventSequencer::CheckForFailure(bool failure_is_fatal, bool success,
-                                          const std::string& error_message) {
-  if (failure_is_fatal) {
-    CHECK(success) << error_message;
-  }
-  if (!success) {
-    LOG(ERROR) << error_message;
-    had_failures_ = true;
-  }
-}
-
-void AsyncEventSequencer::PossiblyRunCompletionActions() {
-  if (!started_ || !outstanding_registrations_.empty()) {
-    // Don't run completion actions if we have any outstanding
-    // Handlers outstanding or if any more handlers might
-    // be scheduled in the future.
-    return;
-  }
-  for (const auto& completion_action : completion_actions_) {
-    // Should this be put on the message loop or run directly?
-    completion_action.Run(!had_failures_);
-  }
-  // Discard our references to those actions.
-  completion_actions_.clear();
-}
-
-}  // namespace dbus_utils
-
-}  // namespace buffet
diff --git a/buffet/async_event_sequencer.h b/buffet/async_event_sequencer.h
deleted file mode 100644
index c16325b..0000000
--- a/buffet/async_event_sequencer.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef BUFFET_ASYNC_EVENT_SEQUENCER_H_
-#define BUFFET_ASYNC_EVENT_SEQUENCER_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/basictypes.h>
-#include <base/memory/ref_counted.h>
-
-namespace buffet {
-
-namespace dbus_utils {
-
-// A helper class for coordinating the multiple async tasks.  A consumer
-// may grab any number of callbacks via Get*Handler() and schedule a list
-// of completion actions to take.  When all handlers obtained via Get*Handler()
-// have been called, the AsyncEventSequencer will call its CompletionActions.
-//
-// Usage:
-//
-// void Init(const base::Callback<void(bool success)> cb) {
-//   scoped_refptr<AsyncEventSequencer> sequencer(
-//       new AsyncEventSequencer());
-//   one_delegate_needing_init_.Init(sequencer->GetHandler(
-//       "my delegate failed to init", false));
-//   dbus_init_delegate_.Init(sequencer->GetExportHandler(
-//       "org.test.Interface", "ExposedMethodName",
-//       "another delegate is flaky", false));
-//   sequencer->OnAllTasksCompletedCall({cb});
-// }
-class AsyncEventSequencer : public base::RefCounted<AsyncEventSequencer> {
- public:
-  typedef base::Callback<void(bool success)> Handler;
-  typedef base::Callback<void (const std::string& interface_name,
-                               const std::string& method_name,
-                               bool success)> ExportHandler;
-  typedef base::Callback<void(bool all_succeeded)> CompletionAction;
-  typedef base::Callback<void(void)> CompletionTask;
-
-  AsyncEventSequencer();
-
-  // Get a Finished handler callback.  Each callback is "unique" in the sense
-  // that subsequent calls to GetHandler() will create new handlers
-  // which will need to be called before completion actions are run.
-  Handler GetHandler(const std::string& descriptive_message,
-                     bool failure_is_fatal);
-
-  // Like GetHandler except with a signature tailored to
-  // ExportedObject's ExportMethod callback requirements.  Will also assert
-  // that the passed interface/method names from ExportedObject are correct.
-  ExportHandler GetExportHandler(
-      const std::string& interface_name, const std::string& method_name,
-      const std::string& descriptive_message, bool failure_is_fatal);
-
-  // Once all handlers obtained via GetHandler have run,
-  // we'll run each CompletionAction, then discard our references.
-  // No more handlers may be obtained after this call.
-  void OnAllTasksCompletedCall(std::vector<CompletionAction> actions);
-
-  // Wrap a CompletionTask with a function that discards the result.
-  // This CompletionTask retains no references to the AsyncEventSequencer.
-  CompletionAction WrapCompletionTask(const CompletionTask& task);
-
- private:
-  // We'll partially bind this function before giving it back via
-  // GetHandler.  Note that the returned callbacks have
-  // references to *this, which gives us the neat property that we'll
-  // destroy *this only when all our callbacks have been destroyed.
-  void HandleFinish(int registration_number, const std::string& error_message,
-                    bool failure_is_fatal, bool success);
-  // Similar to HandleFinish.
-  void HandleDBusMethodExported(
-      const Handler& finish_handler,
-      const std::string& expected_interface_name,
-      const std::string& expected_method_name,
-      const std::string& actual_interface_name,
-      const std::string& actual_method_name,
-      bool success);
-  void RetireRegistration(int registration_number);
-  void CheckForFailure(bool failure_is_fatal, bool success,
-                       const std::string& error_message);
-  void PossiblyRunCompletionActions();
-
-  bool started_{false};
-  int registration_counter_{0};
-  std::set<int> outstanding_registrations_;
-  std::vector<CompletionAction> completion_actions_;
-  bool had_failures_{false};
-  // Ref counted objects have private destructors.
-  ~AsyncEventSequencer();
-  friend class base::RefCounted<AsyncEventSequencer>;
-  DISALLOW_COPY_AND_ASSIGN(AsyncEventSequencer);
-};
-
-}  // namespace dbus_utils
-
-}  // namespace buffet
-
-#endif  // BUFFET_ASYNC_EVENT_SEQUENCER_H_
diff --git a/buffet/async_event_sequencer_unittest.cc b/buffet/async_event_sequencer_unittest.cc
deleted file mode 100644
index d95ff56..0000000
--- a/buffet/async_event_sequencer_unittest.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 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 "buffet/async_event_sequencer.h"
-
-#include <base/bind_helpers.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-namespace buffet {
-
-namespace dbus_utils {
-
-namespace {
-
-const char kTestInterface[] = "org.test.if";
-const char kTestMethod1[] = "TestMethod1";
-const char kTestMethod2[] = "TestMethod2";
-
-}  // namespace
-
-class AsyncEventSequencerTest : public ::testing::Test {
- public:
-  MOCK_METHOD1(HandleCompletion, void(bool all_succeeded));
-
-  void SetUp() {
-      aec_ = new AsyncEventSequencer();
-      cb_ = base::Bind(&AsyncEventSequencerTest::HandleCompletion,
-                       base::Unretained(this));
-  }
-
-  scoped_refptr<AsyncEventSequencer> aec_;
-  AsyncEventSequencer::CompletionAction cb_;
-};
-
-TEST_F(AsyncEventSequencerTest, WaitForCompletionActions) {
-  auto finished_handler = aec_->GetHandler("handler failed", false);
-  finished_handler.Run(true);
-  EXPECT_CALL(*this, HandleCompletion(true)).Times(1);
-  aec_->OnAllTasksCompletedCall({cb_});
-}
-
-TEST_F(AsyncEventSequencerTest, MultiInitActionsSucceed) {
-  auto finished_handler1 = aec_->GetHandler("handler failed", false);
-  auto finished_handler2 = aec_->GetHandler("handler failed", false);
-  aec_->OnAllTasksCompletedCall({cb_});
-  finished_handler1.Run(true);
-  EXPECT_CALL(*this, HandleCompletion(true)).Times(1);
-  finished_handler2.Run(true);
-}
-
-TEST_F(AsyncEventSequencerTest, SomeInitActionsFail) {
-  auto finished_handler1 = aec_->GetHandler("handler failed", false);
-  auto finished_handler2 = aec_->GetHandler("handler failed", false);
-  aec_->OnAllTasksCompletedCall({cb_});
-  finished_handler1.Run(false);
-  EXPECT_CALL(*this, HandleCompletion(false)).Times(1);
-  finished_handler2.Run(true);
-}
-
-TEST_F(AsyncEventSequencerTest, MultiDBusActionsSucceed) {
-  auto handler1 =  aec_->GetExportHandler(
-      kTestInterface, kTestMethod1, "method export failed", false);
-  auto handler2 =  aec_->GetExportHandler(
-      kTestInterface, kTestMethod2, "method export failed", false);
-  aec_->OnAllTasksCompletedCall({cb_});
-  handler1.Run(kTestInterface, kTestMethod1, true);
-  EXPECT_CALL(*this, HandleCompletion(true)).Times(1);
-  handler2.Run(kTestInterface, kTestMethod2, true);
-}
-
-TEST_F(AsyncEventSequencerTest, SomeDBusActionsFail) {
-  auto handler1 =  aec_->GetExportHandler(
-      kTestInterface, kTestMethod1, "method export failed", false);
-  auto handler2 =  aec_->GetExportHandler(
-      kTestInterface, kTestMethod2, "method export failed", false);
-  aec_->OnAllTasksCompletedCall({cb_});
-  handler1.Run(kTestInterface, kTestMethod1, true);
-  EXPECT_CALL(*this, HandleCompletion(false)).Times(1);
-  handler2.Run(kTestInterface, kTestMethod2, false);
-}
-
-TEST_F(AsyncEventSequencerTest, MixedActions) {
-  auto handler1 =  aec_->GetExportHandler(
-      kTestInterface, kTestMethod1, "method export failed", false);
-  auto handler2 = aec_->GetHandler("handler failed", false);
-  aec_->OnAllTasksCompletedCall({cb_});
-  handler1.Run(kTestInterface, kTestMethod1, true);
-  EXPECT_CALL(*this, HandleCompletion(true)).Times(1);
-  handler2.Run(true);
-}
-
-}  // namespace dbus_utils
-
-}  // namespace buffet
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index 001d610..a9300c4 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -5,6 +5,7 @@
         'dbus-1',
         'libchrome-<(libbase_ver)',
         'libchrome-test-<(libbase_ver)',
+        'libchromeos-<(libbase_ver)',
         'libcurl',
         'libmetrics-<(libbase_ver)',
       ],
@@ -24,7 +25,6 @@
       'type': 'static_library',
       'sources': [
         'any.cc',
-        'async_event_sequencer.cc',
         'commands/command_definition.cc',
         'commands/command_dictionary.cc',
         'commands/command_manager.cc',
@@ -84,7 +84,6 @@
       'sources': [
         'any_unittest.cc',
         'any_internal_impl_unittest.cc',
-        'async_event_sequencer_unittest.cc',
         'buffet_testrunner.cc',
         'commands/command_definition_unittest.cc',
         'commands/command_dictionary_unittest.cc',
diff --git a/buffet/exported_object_manager.cc b/buffet/exported_object_manager.cc
index c1403ad..d76e067 100644
--- a/buffet/exported_object_manager.cc
+++ b/buffet/exported_object_manager.cc
@@ -4,9 +4,11 @@
 
 #include "buffet/exported_object_manager.h"
 
+#include <chromeos/async_event_sequencer.h>
 #include <dbus/object_manager.h>
 
-#include "buffet/async_event_sequencer.h"
+
+using chromeos::dbus_utils::AsyncEventSequencer;
 
 namespace buffet {
 
@@ -18,8 +20,7 @@
 
 void ExportedObjectManager::Init(const OnInitFinish& cb) {
   bus_->AssertOnOriginThread();
-  scoped_refptr<dbus_utils::AsyncEventSequencer> sequencer(
-      new dbus_utils::AsyncEventSequencer());
+  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
   exported_object_->ExportMethod(
       dbus::kObjectManagerInterface,
       dbus::kObjectManagerGetManagedObjects,
diff --git a/buffet/exported_property_set.cc b/buffet/exported_property_set.cc
index b1b5633..3ab3c2d 100644
--- a/buffet/exported_property_set.cc
+++ b/buffet/exported_property_set.cc
@@ -5,12 +5,14 @@
 #include "buffet/exported_property_set.h"
 
 #include <base/bind.h>
+#include <chromeos/async_event_sequencer.h>
 #include <dbus/bus.h>  // For kPropertyInterface
 #include <dbus/property.h>  // For kPropertyInterface
 
-#include "buffet/async_event_sequencer.h"
 #include "buffet/dbus_utils.h"
 
+using chromeos::dbus_utils::AsyncEventSequencer;
+
 namespace buffet {
 
 namespace dbus_utils {
diff --git a/buffet/main.cc b/buffet/main.cc
index 358358e..eb25d13 100644
--- a/buffet/main.cc
+++ b/buffet/main.cc
@@ -12,15 +12,15 @@
 #include <base/message_loop/message_loop.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
+#include <chromeos/async_event_sequencer.h>
 #include <dbus/bus.h>
 #include <sysexits.h>
 
-#include "buffet/async_event_sequencer.h"
 #include "buffet/dbus_constants.h"
 #include "buffet/exported_object_manager.h"
 #include "buffet/manager.h"
 
-using buffet::dbus_utils::AsyncEventSequencer;
+using chromeos::dbus_utils::AsyncEventSequencer;
 using buffet::dbus_utils::ExportedObjectManager;
 
 namespace {
diff --git a/buffet/manager.cc b/buffet/manager.cc
index aa29552..0a6af31 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -10,18 +10,18 @@
 #include <base/bind.h>
 #include <base/bind_helpers.h>
 #include <base/json/json_writer.h>
+#include <chromeos/async_event_sequencer.h>
 #include <dbus/bus.h>
 #include <dbus/object_path.h>
 #include <dbus/values_util.h>
 
-#include "buffet/async_event_sequencer.h"
 #include "buffet/commands/command_manager.h"
 #include "buffet/dbus_constants.h"
 #include "buffet/dbus_utils.h"
 #include "buffet/error.h"
 #include "buffet/exported_object_manager.h"
 
-using buffet::dbus_utils::AsyncEventSequencer;
+using chromeos::dbus_utils::AsyncEventSequencer;
 using buffet::dbus_utils::GetBadArgsError;
 using buffet::dbus_utils::GetDBusError;