buffet: Add DBusCommandDispacher and hook it up to CommandQueue

Added DBusCommandDispacher class that maintains DBusCommandProxy object
for each instance of CommandInstance class added to the CommandQueue.

As soon as a command instance is removed from the queue, D-Bus command
dispatcher removes the corresponding command proxy object from D-Bus.

BUG=chromium:374864
TEST=FEATURES=test emerge-link buffet

Change-Id: Ib7ce7370bd3ee471e22f02b8546675021ff063d7
Reviewed-on: https://chromium-review.googlesource.com/211642
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/dbus_command_dispatcher.cc b/buffet/commands/dbus_command_dispatcher.cc
new file mode 100644
index 0000000..e6041d2
--- /dev/null
+++ b/buffet/commands/dbus_command_dispatcher.cc
@@ -0,0 +1,52 @@
+// 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/commands/dbus_command_dispatcher.h"
+
+#include <chromeos/dbus/exported_object_manager.h>
+
+#include "buffet/commands/command_instance.h"
+
+using chromeos::dbus_utils::AsyncEventSequencer;
+using chromeos::dbus_utils::ExportedObjectManager;
+
+namespace buffet {
+
+DBusCommandDispacher::DBusCommandDispacher(
+    const scoped_refptr<dbus::Bus>& bus,
+    ExportedObjectManager* object_manager)
+    : bus_(bus) {
+  if (object_manager)
+    object_manager_ = object_manager->AsWeakPtr();
+}
+
+void DBusCommandDispacher::OnCommandAdded(CommandInstance* command_instance) {
+  auto proxy = CreateDBusCommandProxy(command_instance);
+  proxy->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
+  command_instance->SetProxy(proxy.get());
+
+  auto pair = std::make_pair(command_instance, std::move(proxy));
+  CHECK(command_map_.insert(std::move(pair)).second)
+      << "The command instance is already in the dispatcher command map";
+}
+
+void DBusCommandDispacher::OnCommandRemoved(CommandInstance* command_instance) {
+  command_instance->SetProxy(nullptr);
+  CHECK_GT(command_map_.erase(command_instance), 0u)
+      << "The command instance is not in the dispatcher command map";
+}
+
+DBusCommandProxy* DBusCommandDispacher::FindProxy(
+    CommandInstance* command_instance) const {
+  auto p = command_map_.find(command_instance);
+  return p != command_map_.end() ? p->second.get() : nullptr;
+}
+
+std::unique_ptr<DBusCommandProxy> DBusCommandDispacher::CreateDBusCommandProxy(
+      CommandInstance* command_instance) const {
+  return std::unique_ptr<DBusCommandProxy>(
+      new DBusCommandProxy(object_manager_.get(), bus_, command_instance));
+}
+
+}  // namespace buffet