attestation: Use DBusObject to implement the attestation service

Switch Attestation serivce to use chromeos::dbus_utils::DBusObject
to implement its D-Bus object and use CallMethodAndBlock and
ExtractMethodCallResults from libchromeos to invoke a method
from the client.

BUG=None
TEST=USE=attestation emerge-link platform2

Change-Id: Icbd9f5fdc31ee72f142acdaa17325b6e572ab032
Reviewed-on: https://chromium-review.googlesource.com/215685
Reviewed-by: Nam Nguyen <[email protected]>
Tested-by: Alex Vakulenko <[email protected]>
Commit-Queue: Alex Vakulenko <[email protected]>
diff --git a/client/main.cc b/client/main.cc
index d0411d6..1b0d4fb 100644
--- a/client/main.cc
+++ b/client/main.cc
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+
 #include <base/memory/ref_counted.h>
+#include <chromeos/dbus/dbus_method_invoker.h>
+#include <chromeos/errors/error.h>
 #include <dbus/bus.h>
 #include <dbus/message.h>
 #include <dbus/object_proxy.h>
@@ -17,17 +21,21 @@
   dbus::ObjectProxy* object = bus->GetObjectProxy(
       attestation::kAttestationServiceName,
       dbus::ObjectPath(attestation::kAttestationServicePath));
-  dbus::MethodCall method_call(
+
+  auto response = chromeos::dbus_utils::CallMethodAndBlock(
+      object,
       attestation::kAttestationInterface,
       attestation::kStatsMethod);
-  scoped_ptr<dbus::Response> response(
-      object->CallMethodAndBlock(&method_call,
-                                 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-  attestation::StatsResponse stats;
-  dbus::MessageReader reader(response.get());
-  reader.PopArrayOfBytesAsProto(&stats);
 
-  printf("Attestation has been up for %u seconds.\n", stats.uptime());
+  attestation::StatsResponse stats;
+  chromeos::ErrorPtr error;
+  if (chromeos::dbus_utils::ExtractMethodCallResults(response.get(),
+                                                     &error,
+                                                     &stats)) {
+    printf("Attestation has been up for %u seconds.\n", stats.uptime());
+  } else {
+    printf("Error occurred: %s.\n", error->GetMessage().c_str());
+  }
 
   bus->ShutdownAndBlock();
 
diff --git a/server/attestation_service.cc b/server/attestation_service.cc
index 5b757ee..54d379e 100644
--- a/server/attestation_service.cc
+++ b/server/attestation_service.cc
@@ -6,77 +6,37 @@
 
 #include <string>
 
-#include <base/bind.h>
 #include <base/time/time.h>
+#include <dbus/bus.h>
+#include <dbus/object_path.h>
 
 #include "attestation/common/dbus_interface.pb.h"
 
 namespace attestation {
 
-namespace {
-
-// Passes |method_call| to |handler| and passes the response to
-// |response_sender|. If |handler| returns NULL, an empty response is created
-// and sent.
-static void HandleSynchronousDBusMethodCall(
-    const DBusMethodCallHandler& handler,
-    dbus::MethodCall* method_call,
-    dbus::ExportedObject::ResponseSender response_sender) {
-  ResponsePtr response = handler.Run(method_call);
-  if (!response) {
-    response = dbus::Response::FromMethodCall(method_call);
-  }
-
-  response_sender.Run(response.Pass());
+AttestationService::AttestationService(const scoped_refptr<dbus::Bus>& bus)
+    : start_time_{base::Time()},
+      dbus_object_{nullptr, bus, dbus::ObjectPath{kAttestationServicePath}} {
 }
 
-}  // namespace
+void AttestationService::RegisterAsync(const CompletionAction& callback) {
+  chromeos::dbus_utils::DBusInterface* itf =
+      dbus_object_.AddOrGetInterface(kAttestationInterface);
 
-AttestationService::AttestationService()
-    : start_time_(base::Time()),
-      bus_(nullptr),
-      attestation_dbus_object_(nullptr) {}
+  itf->AddMethodHandler(kStatsMethod,
+                        base::Unretained(this),
+                        &AttestationService::HandleStatsMethod);
 
-AttestationService::~AttestationService() {}
-
-void AttestationService::Init() {
-  dbus::Bus::Options options;
-  options.bus_type = dbus::Bus::SYSTEM;
-  bus_ = new dbus::Bus(options);
-  CHECK(bus_->Connect());
-
-  attestation_dbus_object_ = bus_->GetExportedObject(
-      dbus::ObjectPath(kAttestationServicePath));
-  CHECK(attestation_dbus_object_);
-
-  ExportDBusMethod(kStatsMethod,
-                   base::Bind(&AttestationService::HandleStatsMethod,
-                              base::Unretained(this)));
-
-  CHECK(bus_->RequestOwnershipAndBlock(kAttestationServiceName,
-                                       dbus::Bus::REQUIRE_PRIMARY))
-      << "Unable to take ownership of " << kAttestationServiceName;
+  dbus_object_.RegisterAsync(callback);
 
   start_time_ = base::Time::Now();
 }
 
-void AttestationService::ExportDBusMethod(
-    const std::string& method_name,
-    const DBusMethodCallHandler& handler) {
-  CHECK(attestation_dbus_object_->ExportMethodAndBlock(
-      kAttestationInterface, method_name,
-      base::Bind(&HandleSynchronousDBusMethodCall, handler)));
-}
-
-ResponsePtr AttestationService::HandleStatsMethod(
-    dbus::MethodCall* method_call) {
+StatsResponse AttestationService::HandleStatsMethod(chromeos::ErrorPtr* error) {
   LOG(INFO) << "Received call to stats method.";
   StatsResponse stats;
   stats.set_uptime((base::Time::Now() - start_time_).InSeconds());
-  ResponsePtr response = dbus::Response::FromMethodCall(method_call);
-  dbus::MessageWriter writer(response.get());
-  writer.AppendProtoAsArrayOfBytes(stats);
-  return response.Pass();
+  return stats;
 }
 
 }  // namespace attestation
diff --git a/server/attestation_service.h b/server/attestation_service.h
index bf393db..56eef6d 100644
--- a/server/attestation_service.h
+++ b/server/attestation_service.h
@@ -9,42 +9,33 @@
 
 #include <base/callback.h>
 #include <base/memory/scoped_ptr.h>
-#include <dbus/bus.h>
-#include <dbus/exported_object.h>
-#include <dbus/message.h>
+#include <chromeos/dbus/dbus_object.h>
+#include <chromeos/errors/error.h>
 
 #include "attestation/common/dbus_interface.h"
 
 namespace attestation {
 
 class AttestationService;
-
-typedef scoped_ptr<dbus::Response> ResponsePtr;
-// Pointer to a member function for handling D-Bus method calls. If an empty
-// scoped_ptr is returned, an empty (but successful) response will be sent.
-typedef base::Callback<ResponsePtr (dbus::MethodCall*)> DBusMethodCallHandler;
+class StatsResponse;
+using CompletionAction =
+    chromeos::dbus_utils::AsyncEventSequencer::CompletionAction;
 
 // Main class within the attestation daemon that ties other classes together.
 class AttestationService {
  public:
-  AttestationService();
-  virtual ~AttestationService();
+  explicit AttestationService(const scoped_refptr<dbus::Bus>& bus);
+  virtual ~AttestationService() = default;
 
   // Connects to D-Bus system bus and exports methods.
-  void Init();
+  void RegisterAsync(const CompletionAction& callback);
 
  private:
-  // Exports |method_name| and uses |handler| to handle calls.
-  void ExportDBusMethod(const std::string& method_name,
-                        const DBusMethodCallHandler& handler);
-
   // Callbacks for handling D-Bus signals and method calls.
-  ResponsePtr HandleStatsMethod(dbus::MethodCall* method_call);
+  StatsResponse HandleStatsMethod(chromeos::ErrorPtr* error);
 
   base::Time start_time_;
-  scoped_refptr<dbus::Bus> bus_;
-  // This is owned by bus_.
-  dbus::ExportedObject* attestation_dbus_object_;
+  chromeos::dbus_utils::DBusObject dbus_object_;
 
   DISALLOW_COPY_AND_ASSIGN(AttestationService);
 };
diff --git a/server/main.cc b/server/main.cc
index 7291451..66d622c 100644
--- a/server/main.cc
+++ b/server/main.cc
@@ -5,14 +5,23 @@
 #include <string>
 
 #include <base/at_exit.h>
+#include <base/bind.h>
 #include <base/command_line.h>
 #include <base/message_loop/message_loop.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 #include <chromeos/syslog_logging.h>
+#include <dbus/bus.h>
 
 #include "attestation/server/attestation_service.h"
 
+void TakeServiceOwnership(const scoped_refptr<dbus::Bus>& bus, bool success) {
+  CHECK(success) << "Init of one or more objects has failed.";
+  CHECK(bus->RequestOwnershipAndBlock(attestation::kAttestationServiceName,
+                                      dbus::Bus::REQUIRE_PRIMARY))
+      << "Unable to take ownership of " << attestation::kAttestationServiceName;
+}
+
 int main(int argc, char* argv[]) {
   CommandLine::Init(argc, argv);
 
@@ -20,10 +29,15 @@
 
   base::AtExitManager at_exit_manager;  // This is for the message loop.
   base::MessageLoopForIO message_loop;
+  dbus::Bus::Options options;
+  options.bus_type = dbus::Bus::SYSTEM;
+  scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
+  CHECK(bus->Connect());
 
-  attestation::AttestationService service;
-  service.Init();
+  attestation::AttestationService service(bus);
+  service.RegisterAsync(base::Bind(&TakeServiceOwnership, bus));
 
   message_loop.Run();
+  bus->ShutdownAndBlock();
   return 0;
 }