update_engine: Migrate UE DBus service to chrome DBus bindings.

chromeos-dbus-bindings now generates the adaptor interface that
update_engine exposes over DBus. This interface is implemented in
dbus_service.{h,cc}, which now has a UpdateEngineService class
encapsulating all the service methods implementation.

This allows to write unit test for those methods, which are included
in this CL for all the non-trivial methods.

This CL now uses chrome's DBus bindings for the update_engine serive,
but the proxy interaction is still done using dbus-glib. The main loop
in the main.cc file is now replaced with the chromeos::Dameon, which
uses a chromeos::BaseMessageLoop instead of a GlibMessageLoop. This
causes the asynchronous interactions in the proxy side to not work,
which will be fixed in the next CL.

CQ-DEPEND=CL:290990,CL:291092,CL:293334
BUG=chromium:419827
TEST=Added unittest for all dbus_service methods. deployed and tested manually that update_engine dbus interface works.

Change-Id: I6a6d142b2ac1a61a4c3abcb927665b26114abe5c
Reviewed-on: https://chromium-review.googlesource.com/225324
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Trybot-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/daemon.cc b/daemon.cc
new file mode 100644
index 0000000..bc221b5
--- /dev/null
+++ b/daemon.cc
@@ -0,0 +1,137 @@
+// 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 "update_engine/daemon.h"
+
+#include <sysexits.h>
+
+#include <base/bind.h>
+#include <base/location.h>
+#include <base/time/time.h>
+#include <chromeos/message_loops/message_loop.h>
+
+#include "update_engine/clock.h"
+#include "update_engine/update_attempter.h"
+
+using chromeos::MessageLoop;
+
+namespace {
+const int kDBusSystemMaxWaitSeconds = 2 * 60;
+}  // namespace
+
+namespace chromeos_update_engine {
+
+namespace {
+// Wait for passed |bus| DBus to be connected by attempting to connect it up to
+// |timeout| time. Returns whether the Connect() eventually succeeded.
+bool WaitForDBusSystem(dbus::Bus* bus, base::TimeDelta timeout) {
+  Clock clock;
+  base::Time deadline = clock.GetMonotonicTime() + timeout;
+
+  while (clock.GetMonotonicTime() < deadline) {
+    if (bus->Connect())
+      return true;
+    LOG(WARNING) << "Failed to get system bus, waiting.";
+    // Wait 1 second.
+    sleep(1);
+  }
+  LOG(ERROR) << "Failed to get system bus after " << timeout.InSeconds()
+             << " seconds.";
+  return false;
+}
+}  // namespace
+
+int UpdateEngineDaemon::OnInit() {
+  // Register the |subprocess_| singleton with this Daemon as the signal
+  // handler.
+  subprocess_.Init(this);
+
+  // We use Daemon::OnInit() and not DBusDaemon::OnInit() to gracefully wait for
+  // the D-Bus connection for up two minutes to avoid re-spawning the daemon
+  // too fast causing thrashing if dbus-daemon is not running.
+  int exit_code = Daemon::OnInit();
+  if (exit_code != EX_OK)
+    return exit_code;
+
+  dbus::Bus::Options options;
+  options.bus_type = dbus::Bus::SYSTEM;
+  bus_ = new dbus::Bus(options);
+
+  // Wait for DBus to be ready and exit if it doesn't become available after
+  // the timeout.
+  if (!WaitForDBusSystem(
+          bus_.get(),
+          base::TimeDelta::FromSeconds(kDBusSystemMaxWaitSeconds))) {
+    // TODO(deymo): Make it possible to run update_engine even if dbus-daemon
+    // is not running or constantly crashing.
+    LOG(ERROR) << "Failed to initialize DBus, aborting.";
+    return 1;
+  }
+
+  CHECK(bus_->SetUpAsyncOperations());
+
+  // Initialize update engine global state but continue if something fails.
+  real_system_state_.reset(new RealSystemState(bus_));
+  LOG_IF(ERROR, !real_system_state_->Initialize())
+      << "Failed to initialize system state.";
+  UpdateAttempter* update_attempter = real_system_state_->update_attempter();
+  CHECK(update_attempter);
+
+  // Sets static members for the certificate checker.
+  CertificateChecker::set_system_state(real_system_state_.get());
+  CertificateChecker::set_openssl_wrapper(&openssl_wrapper_);
+
+  // Create the DBus service.
+  dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state_.get(), bus_));
+  update_attempter->set_dbus_adaptor(dbus_adaptor_.get());
+
+  dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered,
+                                          base::Unretained(this)));
+  LOG(INFO) << "Waiting for DBus object to be registered.";
+  return EX_OK;
+}
+
+void UpdateEngineDaemon::OnDBusRegistered(bool succeeded) {
+  if (!succeeded) {
+    LOG(ERROR) << "Registering the UpdateEngineAdaptor";
+    QuitWithExitCode(1);
+    return;
+  }
+
+  // Take ownership of the service now that everything is initialized. We need
+  // to this now and not before to avoid exposing a well known DBus service
+  // path that doesn't have the service it is supposed to implement.
+  if (!dbus_adaptor_->RequestOwnership()) {
+    LOG(ERROR) << "Unable to take ownership of the DBus service, is there "
+               << "other update_engine daemon running?";
+    QuitWithExitCode(1);
+    return;
+  }
+
+  // Initiate update checks.
+  UpdateAttempter* update_attempter = real_system_state_->update_attempter();
+  update_attempter->ScheduleUpdates();
+
+  // Update boot flags after 45 seconds.
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&UpdateAttempter::UpdateBootFlags,
+                 base::Unretained(update_attempter)),
+      base::TimeDelta::FromSeconds(45));
+
+  // Broadcast the update engine status on startup to ensure consistent system
+  // state on crashes.
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &UpdateAttempter::BroadcastStatus,
+      base::Unretained(update_attempter)));
+
+  // Run the UpdateEngineStarted() method on |update_attempter|.
+  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      &UpdateAttempter::UpdateEngineStarted,
+      base::Unretained(update_attempter)));
+
+  LOG(INFO) << "Finished initialization. Now running the loop.";
+}
+
+}  // namespace chromeos_update_engine
diff --git a/daemon.h b/daemon.h
new file mode 100644
index 0000000..4a7fe18
--- /dev/null
+++ b/daemon.h
@@ -0,0 +1,47 @@
+// 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.
+
+#ifndef UPDATE_ENGINE_DAEMON_H_
+#define UPDATE_ENGINE_DAEMON_H_
+
+#include <memory>
+#include <string>
+
+#include <chromeos/daemons/dbus_daemon.h>
+
+#include "update_engine/certificate_checker.h"
+#include "update_engine/dbus_service.h"
+#include "update_engine/real_system_state.h"
+#include "update_engine/subprocess.h"
+
+namespace chromeos_update_engine {
+
+class UpdateEngineDaemon : public chromeos::DBusDaemon {
+ public:
+  UpdateEngineDaemon() = default;
+
+ protected:
+  int OnInit() override;
+
+ private:
+  // Run from the main loop when the |dbus_adaptor_| object is registered. At
+  // this point we can request ownership of the DBus service name and continue
+  // initialization.
+  void OnDBusRegistered(bool succeeded);
+
+  // The Subprocess singleton class requires a chromeos::MessageLoop in the
+  // current thread, so we need to initialize it from this class instead of
+  // the main() function.
+  Subprocess subprocess_;
+
+  std::unique_ptr<RealSystemState> real_system_state_;
+  OpenSSLWrapper openssl_wrapper_;
+  std::unique_ptr<UpdateEngineAdaptor> dbus_adaptor_;
+
+  DISALLOW_COPY_AND_ASSIGN(UpdateEngineDaemon);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_DAEMON_H_
diff --git a/dbus_constants.h b/dbus_constants.h
index d51e6fd..f8494ff 100644
--- a/dbus_constants.h
+++ b/dbus_constants.h
@@ -13,6 +13,10 @@
 static const char* const kUpdateEngineServiceInterface =
     "org.chromium.UpdateEngineInterface";
 
+// Generic UpdateEngine D-Bus error.
+static const char* const kUpdateEngineServiceErrorFailed =
+    "org.chromium.UpdateEngine.Error.Failed";
+
 // Flags used in the AttemptUpdateWithFlags() D-Bus method.
 typedef enum {
   kAttemptUpdateFlagNonInteractive = (1<<0)
diff --git a/dbus_service.cc b/dbus_service.cc
index d77ea31..7c9d0c2 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -7,8 +7,11 @@
 #include <set>
 #include <string>
 
+#include <base/location.h>
 #include <base/logging.h>
 #include <base/strings/stringprintf.h>
+#include <chromeos/bind_lambda.h>
+#include <chromeos/message_loops/message_loop.h>
 #include <chromeos/strings/string_utils.h>
 #include <policy/device_policy.h>
 
@@ -23,400 +26,232 @@
 #include "update_engine/utils.h"
 
 using base::StringPrintf;
+using chromeos::ErrorPtr;
 using chromeos::string_utils::ToString;
 using chromeos_update_engine::AttemptUpdateFlags;
 using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
 using std::set;
 using std::string;
 
-#define UPDATE_ENGINE_SERVICE_ERROR update_engine_service_error_quark ()
-#define UPDATE_ENGINE_SERVICE_TYPE_ERROR \
-  (update_engine_service_error_get_type())
+namespace {
+// Log and set the error on the passed ErrorPtr.
+void LogAndSetError(ErrorPtr *error,
+                    const tracked_objects::Location& location,
+                    const string& reason) {
+  chromeos::Error::AddTo(
+      error, location,
+      chromeos::errors::dbus::kDomain,
+      chromeos_update_engine::kUpdateEngineServiceErrorFailed, reason);
+  LOG(ERROR) << "Sending DBus Failure: " << location.ToString() << ": "
+             << reason;
+}
+}  // namespace
 
-enum UpdateEngineServiceError {
-  UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-  UPDATE_ENGINE_SERVICE_NUM_ERRORS
-};
+namespace chromeos_update_engine {
 
-static GQuark update_engine_service_error_quark(void) {
-  static GQuark ret = 0;
+UpdateEngineService::UpdateEngineService(SystemState* system_state)
+    : system_state_(system_state) {}
 
-  if (ret == 0)
-    ret = g_quark_from_static_string("update_engine_service_error");
+// org::chromium::UpdateEngineInterfaceInterface methods implementation.
 
-  return ret;
+bool UpdateEngineService::AttemptUpdate(ErrorPtr* error,
+                                        const string& in_app_version,
+                                        const string& in_omaha_url) {
+  return AttemptUpdateWithFlags(
+      error, in_app_version, in_omaha_url, 0 /* no flags */);
 }
 
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
-static GType update_engine_service_error_get_type(void) {
-  static GType etype = 0;
-
-  if (etype == 0) {
-    static const GEnumValue values[] = {
-      ENUM_ENTRY(UPDATE_ENGINE_SERVICE_ERROR_FAILED, "Failed"),
-      { 0, 0, 0 }
-    };
-    G_STATIC_ASSERT(UPDATE_ENGINE_SERVICE_NUM_ERRORS ==
-                    G_N_ELEMENTS(values) - 1);
-    etype = g_enum_register_static("UpdateEngineServiceError", values);
-  }
-
-  return etype;
-}
-
-G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)
-
-static void update_engine_service_finalize(GObject* object) {
-  G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
-}
-
-static void log_and_set_response_error(GError** error,
-                                       UpdateEngineServiceError error_code,
-                                       const string& reason) {
-  LOG(ERROR) << "Sending DBus Failure: " << reason;
-  g_set_error_literal(error, UPDATE_ENGINE_SERVICE_ERROR,
-                      error_code, reason.c_str());
-}
-
-static guint status_update_signal = 0;
-
-static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
-  GObjectClass *object_class;
-  object_class = G_OBJECT_CLASS(klass);
-  object_class->finalize = update_engine_service_finalize;
-
-  status_update_signal = g_signal_new(
-      "status_update",
-      G_OBJECT_CLASS_TYPE(klass),
-      G_SIGNAL_RUN_LAST,
-      0,  // 0 == no class method associated
-      nullptr,  // Accumulator
-      nullptr,  // Accumulator data
-      nullptr,  // Marshaller
-      G_TYPE_NONE,  // Return type
-      5,  // param count:
-      G_TYPE_INT64,
-      G_TYPE_DOUBLE,
-      G_TYPE_STRING,
-      G_TYPE_STRING,
-      G_TYPE_INT64);
-}
-
-static void update_engine_service_init(UpdateEngineService* object) {
-  dbus_g_error_domain_register(UPDATE_ENGINE_SERVICE_ERROR,
-                               "org.chromium.UpdateEngine.Error",
-                               UPDATE_ENGINE_SERVICE_TYPE_ERROR);
-}
-
-UpdateEngineService* update_engine_service_new(void) {
-  return reinterpret_cast<UpdateEngineService*>(
-      g_object_new(UPDATE_ENGINE_TYPE_SERVICE, nullptr));
-}
-
-gboolean update_engine_service_attempt_update(UpdateEngineService* self,
-                                              gchar* app_version,
-                                              gchar* omaha_url,
-                                              GError **error) {
-  return update_engine_service_attempt_update_with_flags(self,
-                                                         app_version,
-                                                         omaha_url,
-                                                         0,  // No flags set.
-                                                         error);
-}
-
-gboolean update_engine_service_attempt_update_with_flags(
-    UpdateEngineService* self,
-    gchar* app_version,
-    gchar* omaha_url,
-    gint flags_as_int,
-    GError **error) {
-  string app_version_string, omaha_url_string;
-  AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(flags_as_int);
+bool UpdateEngineService::AttemptUpdateWithFlags(ErrorPtr* /* error */,
+                                                 const string& in_app_version,
+                                                 const string& in_omaha_url,
+                                                 int32_t in_flags_as_int) {
+  AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(in_flags_as_int);
   bool interactive = !(flags & kAttemptUpdateFlagNonInteractive);
 
-  if (app_version)
-    app_version_string = app_version;
-  if (omaha_url)
-    omaha_url_string = omaha_url;
-
-  LOG(INFO) << "Attempt update: app_version=\"" << app_version_string << "\" "
-            << "omaha_url=\"" << omaha_url_string << "\" "
+  LOG(INFO) << "Attempt update: app_version=\"" << in_app_version << "\" "
+            << "omaha_url=\"" << in_omaha_url << "\" "
             << "flags=0x" << std::hex << flags << " "
             << "interactive=" << (interactive? "yes" : "no");
-  self->system_state_->update_attempter()->CheckForUpdate(app_version_string,
-                                                          omaha_url_string,
-                                                          interactive);
-  return TRUE;
+  system_state_->update_attempter()->CheckForUpdate(
+      in_app_version, in_omaha_url, interactive);
+  return true;
 }
 
-gboolean update_engine_service_attempt_rollback(UpdateEngineService* self,
-                                                gboolean powerwash,
-                                                GError **error) {
+bool UpdateEngineService::AttemptRollback(ErrorPtr* error,
+                                          bool in_powerwash) {
   LOG(INFO) << "Attempting rollback to non-active partitions.";
 
-  if (!self->system_state_->update_attempter()->Rollback(powerwash)) {
+  if (!system_state_->update_attempter()->Rollback(in_powerwash)) {
     // TODO(dgarrett): Give a more specific error code/reason.
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Rollback attempt failed.");
-    return FALSE;
+    LogAndSetError(error, FROM_HERE, "Rollback attempt failed.");
+    return false;
   }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_can_rollback(UpdateEngineService* self,
-                                            gboolean* out_can_rollback,
-                                            GError **error) {
-  bool can_rollback = self->system_state_->update_attempter()->CanRollback();
+bool UpdateEngineService::CanRollback(ErrorPtr* /* error */,
+                                      bool* out_can_rollback) {
+  bool can_rollback = system_state_->update_attempter()->CanRollback();
   LOG(INFO) << "Checking to see if we can rollback . Result: " << can_rollback;
   *out_can_rollback = can_rollback;
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_rollback_partition(
-    UpdateEngineService* self,
-    gchar** out_rollback_partition_name,
-    GError **error) {
-  auto name = self->system_state_->update_attempter()->GetRollbackPartition();
-  LOG(INFO) << "Getting rollback partition name. Result: " << name;
-  *out_rollback_partition_name = g_strdup(name.c_str());
-  return TRUE;
-}
-
-gboolean update_engine_service_get_kernel_devices(UpdateEngineService* self,
-                                                  gchar** out_kernel_devices,
-                                                  GError **error) {
-  auto devices = self->system_state_->update_attempter()->GetKernelDevices();
-  string info;
-  for (const auto& device : devices) {
-    base::StringAppendF(&info, "%d:%s\n",
-                        device.second ? 1 : 0, device.first.c_str());
-  }
-  LOG(INFO) << "Available kernel devices: " << info;
-  *out_kernel_devices = g_strdup(info.c_str());
-  return TRUE;
-}
-
-
-gboolean update_engine_service_reset_status(UpdateEngineService* self,
-                                            GError **error) {
-  if (!self->system_state_->update_attempter()->ResetStatus()) {
+bool UpdateEngineService::ResetStatus(ErrorPtr* error) {
+  if (!system_state_->update_attempter()->ResetStatus()) {
     // TODO(dgarrett): Give a more specific error code/reason.
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "ResetStatus failed.");
-    return FALSE;
+    LogAndSetError(error, FROM_HERE, "ResetStatus failed.");
+    return false;
   }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_status(UpdateEngineService* self,
-                                          int64_t* last_checked_time,
-                                          double* progress,
-                                          gchar** current_operation,
-                                          gchar** new_version,
-                                          int64_t* new_size,
-                                          GError **error) {
-  string current_op;
-  string new_version_str;
-
-  CHECK(self->system_state_->update_attempter()->GetStatus(last_checked_time,
-                                                           progress,
-                                                           &current_op,
-                                                           &new_version_str,
-                                                           new_size));
-  *current_operation = g_strdup(current_op.c_str());
-  *new_version = g_strdup(new_version_str.c_str());
-
-  if (!*current_operation) {
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Unable to find current_operation.");
-    return FALSE;
+bool UpdateEngineService::GetStatus(ErrorPtr* error,
+                                    int64_t* out_last_checked_time,
+                                    double* out_progress,
+                                    string* out_current_operation,
+                                    string* out_new_version,
+                                    int64_t* out_new_size) {
+  if (!system_state_->update_attempter()->GetStatus(out_last_checked_time,
+                                                    out_progress,
+                                                    out_current_operation,
+                                                    out_new_version,
+                                                    out_new_size)) {
+    LogAndSetError(error, FROM_HERE, "GetStatus failed.");
+    return false;
   }
-
-  if (!*new_version) {
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Unable to find vew_version.");
-    return FALSE;
-  }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
-                                                GError **error) {
-  if (!self->system_state_->update_attempter()->RebootIfNeeded()) {
+bool UpdateEngineService::RebootIfNeeded(ErrorPtr* error) {
+  if (!system_state_->update_attempter()->RebootIfNeeded()) {
     // TODO(dgarrett): Give a more specific error code/reason.
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Reboot not needed, or attempt failed.");
-    return FALSE;
+    LogAndSetError(error, FROM_HERE, "Reboot not needed, or attempt failed.");
+    return false;
   }
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_set_channel(UpdateEngineService* self,
-                                           gchar* target_channel,
-                                           gboolean is_powerwash_allowed,
-                                           GError **error) {
-  if (!target_channel) {
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Target channel to set not specified.");
-    return FALSE;
-  }
-
-  const policy::DevicePolicy* device_policy =
-      self->system_state_->device_policy();
+bool UpdateEngineService::SetChannel(ErrorPtr* error,
+                                     const string& in_target_channel,
+                                     bool in_is_powerwash_allowed) {
+  const policy::DevicePolicy* device_policy = system_state_->device_policy();
 
   // The device_policy is loaded in a lazy way before an update check. Load it
   // now from the libchromeos cache if it wasn't already loaded.
   if (!device_policy) {
-    chromeos_update_engine::UpdateAttempter* update_attempter =
-        self->system_state_->update_attempter();
+    UpdateAttempter* update_attempter = system_state_->update_attempter();
     if (update_attempter) {
       update_attempter->RefreshDevicePolicy();
-      device_policy = self->system_state_->device_policy();
+      device_policy = system_state_->device_policy();
     }
   }
 
   bool delegated = false;
   if (device_policy &&
       device_policy->GetReleaseChannelDelegated(&delegated) && !delegated) {
-    log_and_set_response_error(
-        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
+    LogAndSetError(
+        error, FROM_HERE,
         "Cannot set target channel explicitly when channel "
         "policy/settings is not delegated");
-    return FALSE;
+    return false;
   }
 
-  LOG(INFO) << "Setting destination channel to: " << target_channel;
-  if (!self->system_state_->request_params()->SetTargetChannel(
-          target_channel, is_powerwash_allowed)) {
+  LOG(INFO) << "Setting destination channel to: " << in_target_channel;
+  if (!system_state_->request_params()->SetTargetChannel(
+          in_target_channel, in_is_powerwash_allowed)) {
     // TODO(dgarrett): Give a more specific error code/reason.
-    log_and_set_response_error(error,
-                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Setting channel failed.");
-    return FALSE;
+    LogAndSetError(error, FROM_HERE, "Setting channel failed.");
+    return false;
   }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_channel(UpdateEngineService* self,
-                                           gboolean get_current_channel,
-                                           gchar** channel,
-                                           GError **error) {
-  chromeos_update_engine::OmahaRequestParams* rp =
-      self->system_state_->request_params();
-
-  string channel_str = get_current_channel ?
-      rp->current_channel() : rp->target_channel();
-
-  *channel = g_strdup(channel_str.c_str());
-  return TRUE;
+bool UpdateEngineService::GetChannel(ErrorPtr* /* error */,
+                                     bool in_get_current_channel,
+                                     string* out_channel) {
+  OmahaRequestParams* rp = system_state_->request_params();
+  *out_channel = (in_get_current_channel ?
+                  rp->current_channel() : rp->target_channel());
+  return true;
 }
 
-gboolean update_engine_service_set_p2p_update_permission(
-    UpdateEngineService* self,
-    gboolean enabled,
-    GError **error) {
-  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
+bool UpdateEngineService::SetP2PUpdatePermission(ErrorPtr* error,
+                                                 bool in_enabled) {
+  PrefsInterface* prefs = system_state_->prefs();
 
-  if (!prefs->SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, enabled)) {
-    log_and_set_response_error(
-        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
+  if (!prefs->SetBoolean(kPrefsP2PEnabled, in_enabled)) {
+    LogAndSetError(
+        error, FROM_HERE,
         StringPrintf("Error setting the update via p2p permission to %s.",
-                     ToString(enabled).c_str()));
-    return FALSE;
+                     ToString(in_enabled).c_str()));
+    return false;
   }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_p2p_update_permission(
-    UpdateEngineService* self,
-    gboolean* enabled,
-    GError **error) {
-  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
+bool UpdateEngineService::GetP2PUpdatePermission(ErrorPtr* error,
+                                                 bool* out_enabled) {
+  PrefsInterface* prefs = system_state_->prefs();
 
   bool p2p_pref = false;  // Default if no setting is present.
-  if (prefs->Exists(chromeos_update_engine::kPrefsP2PEnabled) &&
-      !prefs->GetBoolean(chromeos_update_engine::kPrefsP2PEnabled, &p2p_pref)) {
-    log_and_set_response_error(error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "Error getting the P2PEnabled setting.");
-    return FALSE;
+  if (prefs->Exists(kPrefsP2PEnabled) &&
+      !prefs->GetBoolean(kPrefsP2PEnabled, &p2p_pref)) {
+    LogAndSetError(error, FROM_HERE, "Error getting the P2PEnabled setting.");
+    return false;
   }
 
-  *enabled = p2p_pref;
-  return TRUE;
+  *out_enabled = p2p_pref;
+  return true;
 }
 
-gboolean update_engine_service_set_update_over_cellular_permission(
-    UpdateEngineService* self,
-    gboolean allowed,
-    GError **error) {
+bool UpdateEngineService::SetUpdateOverCellularPermission(ErrorPtr* error,
+                                                          bool in_allowed) {
   set<string> allowed_types;
-  const policy::DevicePolicy* device_policy =
-      self->system_state_->device_policy();
+  const policy::DevicePolicy* device_policy = system_state_->device_policy();
 
   // The device_policy is loaded in a lazy way before an update check. Load it
   // now from the libchromeos cache if it wasn't already loaded.
   if (!device_policy) {
-    chromeos_update_engine::UpdateAttempter* update_attempter =
-        self->system_state_->update_attempter();
+    UpdateAttempter* update_attempter = system_state_->update_attempter();
     if (update_attempter) {
       update_attempter->RefreshDevicePolicy();
-      device_policy = self->system_state_->device_policy();
+      device_policy = system_state_->device_policy();
     }
   }
 
   // Check if this setting is allowed by the device policy.
   if (device_policy &&
       device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
-    log_and_set_response_error(
-        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-        "Ignoring the update over cellular setting since there's "
-        "a device policy enforcing this setting.");
-    return FALSE;
+    LogAndSetError(error, FROM_HERE,
+                   "Ignoring the update over cellular setting since there's "
+                   "a device policy enforcing this setting.");
+    return false;
   }
 
   // If the policy wasn't loaded yet, then it is still OK to change the local
   // setting because the policy will be checked again during the update check.
 
-  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
+  PrefsInterface* prefs = system_state_->prefs();
 
-  if (!prefs->SetBoolean(
-      chromeos_update_engine::kPrefsUpdateOverCellularPermission,
-      allowed)) {
-    log_and_set_response_error(
-        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-        string("Error setting the update over cellular to ") +
-        (allowed ? "true" : "false"));
-    return FALSE;
+  if (!prefs->SetBoolean(kPrefsUpdateOverCellularPermission, in_allowed)) {
+    LogAndSetError(error, FROM_HERE,
+                   string("Error setting the update over cellular to ") +
+                   (in_allowed ? "true" : "false"));
+    return false;
   }
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_update_over_cellular_permission(
-    UpdateEngineService* self,
-    gboolean* allowed,
-    GError **error) {
-  chromeos_update_engine::ConnectionManagerInterface* cm =
-      self->system_state_->connection_manager();
+bool UpdateEngineService::GetUpdateOverCellularPermission(ErrorPtr* /* error */,
+                                                          bool* out_allowed) {
+  ConnectionManagerInterface* cm = system_state_->connection_manager();
 
   // The device_policy is loaded in a lazy way before an update check and is
   // used to determine if an update is allowed over cellular. Load the device
   // policy now from the libchromeos cache if it wasn't already loaded.
-  if (!self->system_state_->device_policy()) {
-    chromeos_update_engine::UpdateAttempter* update_attempter =
-        self->system_state_->update_attempter();
+  if (!system_state_->device_policy()) {
+    UpdateAttempter* update_attempter = system_state_->update_attempter();
     if (update_attempter)
       update_attempter->RefreshDevicePolicy();
   }
@@ -424,53 +259,70 @@
   // Return the current setting based on the same logic used while checking for
   // updates. A log message could be printed as the result of this test.
   LOG(INFO) << "Checking if updates over cellular networks are allowed:";
-  *allowed = cm->IsUpdateAllowedOver(
+  *out_allowed = cm->IsUpdateAllowedOver(
       chromeos_update_engine::NetworkConnectionType::kCellular,
       chromeos_update_engine::NetworkTethering::kUnknown);
-
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_get_duration_since_update(
-    UpdateEngineService* self,
-    gint64* out_usec_wallclock,
-    GError **error) {
-
+bool UpdateEngineService::GetDurationSinceUpdate(ErrorPtr* error,
+                                                 int64_t* out_usec_wallclock) {
   base::Time time;
-  if (!self->system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) {
-    log_and_set_response_error(error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
-                               "No pending update.");
-    return FALSE;
+  if (!system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) {
+    LogAndSetError(error, FROM_HERE, "No pending update.");
+    return false;
   }
 
-  chromeos_update_engine::ClockInterface *clock = self->system_state_->clock();
+  ClockInterface* clock = system_state_->clock();
   *out_usec_wallclock = (clock->GetBootTime() - time).InMicroseconds();
-  return TRUE;
+  return true;
 }
 
-gboolean update_engine_service_emit_status_update(
-    UpdateEngineService* self,
-    gint64 last_checked_time,
-    gdouble progress,
-    const gchar* current_operation,
-    const gchar* new_version,
-    gint64 new_size) {
-  g_signal_emit(self,
-                status_update_signal,
-                0,
-                last_checked_time,
-                progress,
-                current_operation,
-                new_version,
-                new_size);
-  return TRUE;
+bool UpdateEngineService::GetPrevVersion(ErrorPtr* /* error */,
+                                         string* out_prev_version) {
+  *out_prev_version = system_state_->update_attempter()->GetPrevVersion();
+  return true;
 }
 
-gboolean update_engine_service_get_prev_version(
-    UpdateEngineService* self,
-    gchar** prev_version,
-    GError **error) {
-  string ver = self->system_state_->update_attempter()->GetPrevVersion();
-  *prev_version = g_strdup(ver.c_str());
-  return TRUE;
+bool UpdateEngineService::GetKernelDevices(ErrorPtr* /* error */,
+                                           string* out_kernel_devices) {
+  auto devices = system_state_->update_attempter()->GetKernelDevices();
+  string info;
+  for (const auto& device : devices) {
+    base::StringAppendF(&info, "%d:%s\n",
+                        device.second ? 1 : 0, device.first.c_str());
+  }
+  LOG(INFO) << "Available kernel devices: " << info;
+  *out_kernel_devices = info;
+  return true;
 }
+
+bool UpdateEngineService::GetRollbackPartition(
+    ErrorPtr* /* error */,
+    string* out_rollback_partition_name) {
+  string name = system_state_->update_attempter()->GetRollbackPartition();
+  LOG(INFO) << "Getting rollback partition name. Result: " << name;
+  *out_rollback_partition_name = name;
+  return true;
+}
+
+
+UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state,
+                                         const scoped_refptr<dbus::Bus>& bus)
+    : org::chromium::UpdateEngineInterfaceAdaptor(&dbus_service_),
+    bus_(bus),
+    dbus_service_(system_state),
+    dbus_object_(nullptr, bus, dbus::ObjectPath(kUpdateEngineServicePath)) {}
+
+void UpdateEngineAdaptor::RegisterAsync(
+    const base::Callback<void(bool)>& completion_callback) {
+  RegisterWithDBusObject(&dbus_object_);
+  dbus_object_.RegisterAsync(completion_callback);
+}
+
+bool UpdateEngineAdaptor::RequestOwnership() {
+  return bus_->RequestOwnershipAndBlock(kUpdateEngineServiceName,
+                                        dbus::Bus::REQUIRE_PRIMARY);
+}
+
+}  // namespace chromeos_update_engine
diff --git a/dbus_service.h b/dbus_service.h
index d61e3b5..6429240 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -7,171 +7,153 @@
 
 #include <inttypes.h>
 
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <glib-object.h>
+#include <string>
+
+#include <base/memory/ref_counted.h>
+#include <chromeos/errors/error.h>
 
 #include "update_engine/update_attempter.h"
 
-// Type macros:
-#define UPDATE_ENGINE_TYPE_SERVICE (update_engine_service_get_type())
-#define UPDATE_ENGINE_SERVICE(obj)                                      \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), UPDATE_ENGINE_TYPE_SERVICE,        \
-                              UpdateEngineService))
-#define UPDATE_ENGINE_IS_SERVICE(obj)                                   \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), UPDATE_ENGINE_TYPE_SERVICE))
-#define UPDATE_ENGINE_SERVICE_CLASS(klass)                      \
-  (G_TYPE_CHECK_CLASS_CAST((klass), UPDATE_ENGINE_TYPE_SERVICE, \
-                           UpdateEngineService))
-#define UPDATE_ENGINE_IS_SERVICE_CLASS(klass)                           \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), UPDATE_ENGINE_TYPE_SERVICE))
-#define UPDATE_ENGINE_SERVICE_GET_CLASS(obj)                    \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), UPDATE_ENGINE_TYPE_SERVICE, \
-                             UpdateEngineService))
+#include "update_engine/dbus_adaptor/org.chromium.UpdateEngineInterface.h"
 
-G_BEGIN_DECLS
+namespace chromeos {
+namespace dbus {
+class Bus;
+}  // namespace dbus
+}  // namespace chromeos
 
-struct UpdateEngineService {
-  GObject parent_instance;
+namespace chromeos_update_engine {
 
-  chromeos_update_engine::SystemState* system_state_;
+class UpdateEngineService
+    : public org::chromium::UpdateEngineInterfaceInterface {
+ public:
+  explicit UpdateEngineService(SystemState* system_state);
+  virtual ~UpdateEngineService() = default;
+
+  // Implementation of org::chromium::UpdateEngineInterfaceInterface.
+  bool AttemptUpdate(chromeos::ErrorPtr* error,
+                     const std::string& in_app_version,
+                     const std::string& in_omaha_url) override;
+
+  bool AttemptUpdateWithFlags(chromeos::ErrorPtr* error,
+                              const std::string& in_app_version,
+                              const std::string& in_omaha_url,
+                              int32_t in_flags_as_int) override;
+
+  bool AttemptRollback(chromeos::ErrorPtr* error, bool in_powerwash) override;
+
+  // Checks if the system rollback is available by verifying if the secondary
+  // system partition is valid and bootable.
+  bool CanRollback(chromeos::ErrorPtr* error, bool* out_can_rollback) override;
+
+  // Resets the status of the update_engine to idle, ignoring any applied
+  // update. This is used for development only.
+  bool ResetStatus(chromeos::ErrorPtr* error) override;
+
+  // Returns the current status of the Update Engine. If an update is in
+  // progress, the number of operations, size to download and overall progress
+  // is reported.
+  bool GetStatus(chromeos::ErrorPtr* error,
+                 int64_t* out_last_checked_time,
+                 double* out_progress,
+                 std::string* out_current_operation,
+                 std::string* out_new_version,
+                 int64_t* out_new_size) override;
+
+  // Reboots the device if an update is applied and a reboot is required.
+  bool RebootIfNeeded(chromeos::ErrorPtr* error) override;
+
+  // Changes the current channel of the device to the target channel. If the
+  // target channel is a less stable channel than the current channel, then the
+  // channel change happens immediately (at the next update check).  If the
+  // target channel is a more stable channel, then if is_powerwash_allowed is
+  // set to true, then also the change happens immediately but with a powerwash
+  // if required. Otherwise, the change takes effect eventually (when the
+  // version on the target channel goes above the version number of what the
+  // device currently has).
+  bool SetChannel(chromeos::ErrorPtr* error,
+                  const std::string& in_target_channel,
+                  bool in_is_powerwash_allowed) override;
+
+  // If get_current_channel is set to true, populates |channel| with the name of
+  // the channel that the device is currently on. Otherwise, it populates it
+  // with the name of the channel the device is supposed to be (in case of a
+  // pending channel change).
+  bool GetChannel(chromeos::ErrorPtr* error,
+                  bool in_get_current_channel,
+                  std::string* out_channel) override;
+
+  // Enables or disables the sharing and consuming updates over P2P feature
+  // according to the |enabled| argument passed.
+  bool SetP2PUpdatePermission(chromeos::ErrorPtr* error,
+                              bool in_enabled) override;
+
+  // Returns the current value for the P2P enabled setting. This involves both
+  // sharing and consuming updates over P2P.
+  bool GetP2PUpdatePermission(chromeos::ErrorPtr* error,
+                              bool* out_enabled) override;
+
+  // If there's no device policy installed, sets the update over cellular
+  // networks permission to the |allowed| value. Otherwise, this method returns
+  // with an error since this setting is overridden by the applied policy.
+  bool SetUpdateOverCellularPermission(chromeos::ErrorPtr* error,
+                                       bool in_allowed) override;
+
+  // Returns the current value of the update over cellular network setting,
+  // either forced by the device policy if the device is enrolled or the current
+  // user preference otherwise.
+  bool GetUpdateOverCellularPermission(chromeos::ErrorPtr* error,
+                                       bool* out_allowed) override;
+
+  // Returns the duration since the last successful update, as the
+  // duration on the wallclock. Returns an error if the device has not
+  // updated.
+  bool GetDurationSinceUpdate(chromeos::ErrorPtr* error,
+                              int64_t* out_usec_wallclock) override;
+
+  // Returns the version string of OS that was used before the last reboot
+  // into an updated version. This is available only when rebooting into an
+  // update from previous version, otherwise an empty string is returned.
+  bool GetPrevVersion(chromeos::ErrorPtr* error,
+                      std::string* out_prev_version) override;
+
+  // Returns a list of available kernel partitions and whether each of them
+  // can be booted from or not.
+  bool GetKernelDevices(chromeos::ErrorPtr* error,
+                        std::string* out_kernel_devices) override;
+
+  // Returns the name of kernel partition that can be rolled back into.
+  bool GetRollbackPartition(chromeos::ErrorPtr* error,
+                            std::string* out_rollback_partition_name) override;
+
+ private:
+  SystemState* system_state_;
 };
 
-struct UpdateEngineServiceClass {
-  GObjectClass parent_class;
+// The UpdateEngineAdaptor class runs the UpdateEngineInterface in the fixed
+// object path, without an ObjectManager notifying the interfaces, since it is
+// all static and clients don't expect it to be implemented.
+class UpdateEngineAdaptor : public org::chromium::UpdateEngineInterfaceAdaptor {
+ public:
+  UpdateEngineAdaptor(SystemState* system_state,
+                      const scoped_refptr<dbus::Bus>& bus);
+  ~UpdateEngineAdaptor() = default;
+
+  // Register the DBus object with the update engine service asynchronously.
+  // Calls |copmletion_callback| when done passing a boolean indicating if the
+  // registration succeeded.
+  void RegisterAsync(const base::Callback<void(bool)>& completion_callback);
+
+  // Takes ownership of the well-known DBus name and returns whether it
+  // succeeded.
+  bool RequestOwnership();
+
+ private:
+  scoped_refptr<dbus::Bus> bus_;
+  UpdateEngineService dbus_service_;
+  chromeos::dbus_utils::DBusObject dbus_object_;
 };
 
-UpdateEngineService* update_engine_service_new(void);
-GType update_engine_service_get_type(void);
-
-// Methods
-
-gboolean update_engine_service_attempt_update(UpdateEngineService* self,
-                                              gchar* app_version,
-                                              gchar* omaha_url,
-                                              GError **error);
-
-gboolean update_engine_service_attempt_update_with_flags(
-    UpdateEngineService* self,
-    gchar* app_version,
-    gchar* omaha_url,
-    gint flags_as_int,
-    GError **error);
-
-gboolean update_engine_service_attempt_rollback(UpdateEngineService* self,
-                                                gboolean powerwash,
-                                                GError **error);
-
-// Checks if the system rollback is available by verifying if the secondary
-// system partition is valid and bootable.
-gboolean update_engine_service_can_rollback(
-    UpdateEngineService* self,
-    gboolean* out_can_rollback,
-    GError **error);
-
-// Returns the name of kernel partition that can be rolled back into.
-gboolean update_engine_service_get_rollback_partition(
-  UpdateEngineService* self,
-  gchar** out_rollback_partition_name,
-  GError **error);
-
-// Returns a list of available kernel partitions and whether each of them
-// can be booted from or not.
-gboolean update_engine_service_get_kernel_devices(UpdateEngineService* self,
-                                                  gchar** out_kernel_devices,
-                                                  GError **error);
-
-gboolean update_engine_service_reset_status(UpdateEngineService* self,
-                                            GError **error);
-
-gboolean update_engine_service_get_status(UpdateEngineService* self,
-                                          int64_t* last_checked_time,
-                                          double* progress,
-                                          gchar** current_operation,
-                                          gchar** new_version,
-                                          int64_t* new_size,
-                                          GError **error);
-
-gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
-                                                GError **error);
-
-// Changes the current channel of the device to the target channel. If the
-// target channel is a less stable channel than the current channel, then the
-// channel change happens immediately (at the next update check).  If the
-// target channel is a more stable channel, then if is_powerwash_allowed is set
-// to true, then also the change happens immediately but with a powerwash if
-// required. Otherwise, the change takes effect eventually (when the version on
-// the target channel goes above the version number of what the device
-// currently has).
-gboolean update_engine_service_set_channel(UpdateEngineService* self,
-                                           gchar* target_channel,
-                                           gboolean is_powerwash_allowed,
-                                           GError **error);
-
-// If get_current_channel is set to true, populates |channel| with the name of
-// the channel that the device is currently on. Otherwise, it populates it with
-// the name of the channel the device is supposed to be (in case of a pending
-// channel change).
-gboolean update_engine_service_get_channel(UpdateEngineService* self,
-                                           gboolean get_current_channel,
-                                           gchar** channel,
-                                           GError **error);
-
-// Enables or disables the sharing and consuming updates over P2P feature
-// according to the |enabled| argument passed.
-gboolean update_engine_service_set_p2p_update_permission(
-    UpdateEngineService* self,
-    gboolean enabled,
-    GError **error);
-
-// Returns in |enabled| the current value for the P2P enabled setting. This
-// involves both sharing and consuming updates over P2P.
-gboolean update_engine_service_get_p2p_update_permission(
-    UpdateEngineService* self,
-    gboolean* enabled,
-    GError **error);
-
-// If there's no device policy installed, sets the update over cellular networks
-// permission to the |allowed| value. Otherwise, this method returns with an
-// error since this setting is overridden by the applied policy.
-gboolean update_engine_service_set_update_over_cellular_permission(
-    UpdateEngineService* self,
-    gboolean allowed,
-    GError **error);
-
-// Returns the current value of the update over cellular network setting, either
-// forced by the device policy if the device is enrolled or the current user
-// preference otherwise.
-gboolean update_engine_service_get_update_over_cellular_permission(
-    UpdateEngineService* self,
-    gboolean* allowed,
-    GError **error);
-
-// Returns the duration since the last successful update, as the
-// duration on the wallclock. Returns an error if the device has not
-// updated.
-gboolean update_engine_service_get_duration_since_update(
-    UpdateEngineService* self,
-    gint64* out_usec_wallclock,
-    GError **error);
-
-gboolean update_engine_service_emit_status_update(
-    UpdateEngineService* self,
-    gint64 last_checked_time,
-    gdouble progress,
-    const gchar* current_operation,
-    const gchar* new_version,
-    gint64 new_size);
-
-// Returns the version string of OS that was used before the last reboot
-// into an updated version. This is available only when rebooting into an
-// update from previous version, otherwise an empty string is returned.
-gboolean update_engine_service_get_prev_version(
-    UpdateEngineService* self,
-    gchar** prev_version,
-    GError **error);
-
-G_END_DECLS
+}  // namespace chromeos_update_engine
 
 #endif  // UPDATE_ENGINE_DBUS_SERVICE_H_
diff --git a/dbus_service_unittest.cc b/dbus_service_unittest.cc
new file mode 100644
index 0000000..441f89d
--- /dev/null
+++ b/dbus_service_unittest.cc
@@ -0,0 +1,130 @@
+// 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 "update_engine/dbus_service.h"
+
+#include <gtest/gtest.h>
+#include <string>
+
+#include <chromeos/errors/error.h>
+#include <policy/libpolicy.h>
+#include <policy/mock_device_policy.h>
+
+#include "update_engine/dbus_constants.h"
+#include "update_engine/fake_system_state.h"
+
+using std::string;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::_;
+
+using chromeos::errors::dbus::kDomain;
+
+namespace chromeos_update_engine {
+
+class UpdateEngineServiceTest : public ::testing::Test {
+ protected:
+  UpdateEngineServiceTest()
+      : mock_update_attempter_(fake_system_state_.mock_update_attempter()),
+        dbus_service_(&fake_system_state_) {}
+
+  void SetUp() override {
+    fake_system_state_.set_device_policy(nullptr);
+  }
+
+  // Fake/mock infrastructure.
+  FakeSystemState fake_system_state_;
+  policy::MockDevicePolicy mock_device_policy_;
+
+  // Shortcut for fake_system_state_.mock_update_attempter().
+  MockUpdateAttempter* mock_update_attempter_;
+
+  chromeos::ErrorPtr error_;
+  UpdateEngineService dbus_service_;
+};
+
+TEST_F(UpdateEngineServiceTest, AttemptUpdate) {
+  // Simple test to ensure that the default is an interactive check.
+  EXPECT_CALL(*mock_update_attempter_,
+              CheckForUpdate("app_ver", "url", true /* interactive */));
+  EXPECT_TRUE(dbus_service_.AttemptUpdate(&error_, "app_ver", "url"));
+  EXPECT_EQ(nullptr, error_);
+}
+
+TEST_F(UpdateEngineServiceTest, AttemptUpdateWithFlags) {
+  EXPECT_CALL(*mock_update_attempter_, CheckForUpdate(
+      "app_ver", "url", false /* interactive */));
+  // The update is non-interactive when we pass the non-interactive flag.
+  EXPECT_TRUE(dbus_service_.AttemptUpdateWithFlags(
+      &error_, "app_ver", "url", kAttemptUpdateFlagNonInteractive));
+  EXPECT_EQ(nullptr, error_);
+}
+
+// SetChannel is allowed when there's no device policy (the device is not
+// enterprise enrolled).
+TEST_F(UpdateEngineServiceTest, SetChannelWithNoPolicy) {
+  EXPECT_CALL(*mock_update_attempter_, RefreshDevicePolicy());
+  // If SetTargetChannel is called it means the policy check passed.
+  EXPECT_CALL(*fake_system_state_.mock_request_params(),
+              SetTargetChannel("stable-channel", true))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(dbus_service_.SetChannel(&error_, "stable-channel", true));
+  ASSERT_EQ(nullptr, error_);
+}
+
+// When the policy is present, the delegated value should be checked.
+TEST_F(UpdateEngineServiceTest, SetChannelWithDelegatedPolicy) {
+  policy::MockDevicePolicy mock_device_policy;
+  fake_system_state_.set_device_policy(&mock_device_policy);
+  EXPECT_CALL(mock_device_policy, GetReleaseChannelDelegated(_))
+      .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
+  EXPECT_CALL(*fake_system_state_.mock_request_params(),
+              SetTargetChannel("beta-channel", true))
+      .WillOnce(Return(true));
+
+  EXPECT_TRUE(dbus_service_.SetChannel(&error_, "beta-channel", true));
+  ASSERT_EQ(nullptr, error_);
+}
+
+// When passing an invalid value (SetTargetChannel fails) an error should be
+// raised.
+TEST_F(UpdateEngineServiceTest, SetChannelWithInvalidChannel) {
+  EXPECT_CALL(*mock_update_attempter_, RefreshDevicePolicy());
+  EXPECT_CALL(*fake_system_state_.mock_request_params(),
+              SetTargetChannel("foo-channel", true)).WillOnce(Return(false));
+
+  EXPECT_FALSE(dbus_service_.SetChannel(&error_, "foo-channel", true));
+  ASSERT_NE(nullptr, error_);
+  EXPECT_TRUE(error_->HasError(kDomain, kUpdateEngineServiceErrorFailed));
+}
+
+TEST_F(UpdateEngineServiceTest, GetChannel) {
+  fake_system_state_.mock_request_params()->set_current_channel("current");
+  fake_system_state_.mock_request_params()->set_target_channel("target");
+  string channel;
+  EXPECT_TRUE(dbus_service_.GetChannel(
+      &error_, true /* get_current_channel */, &channel));
+  EXPECT_EQ(nullptr, error_);
+  EXPECT_EQ("current", channel);
+
+  EXPECT_TRUE(dbus_service_.GetChannel(
+      &error_, false /* get_current_channel */, &channel));
+  EXPECT_EQ(nullptr, error_);
+  EXPECT_EQ("target", channel);
+}
+
+TEST_F(UpdateEngineServiceTest, ResetStatusSucceeds) {
+  EXPECT_CALL(*mock_update_attempter_, ResetStatus()).WillOnce(Return(true));
+  EXPECT_TRUE(dbus_service_.ResetStatus(&error_));
+  EXPECT_EQ(nullptr, error_);
+}
+
+TEST_F(UpdateEngineServiceTest, ResetStatusFails) {
+  EXPECT_CALL(*mock_update_attempter_, ResetStatus()).WillOnce(Return(false));
+  EXPECT_FALSE(dbus_service_.ResetStatus(&error_));
+  ASSERT_NE(nullptr, error_);
+  EXPECT_TRUE(error_->HasError(kDomain, kUpdateEngineServiceErrorFailed));
+}
+
+}  // namespace chromeos_update_engine
diff --git a/main.cc b/main.cc
index cf06f2a..4fe0c84 100644
--- a/main.cc
+++ b/main.cc
@@ -5,101 +5,30 @@
 #include <unistd.h>
 
 #include <string>
-#include <vector>
 
 #include <base/at_exit.h>
 #include <base/command_line.h>
 #include <base/files/file_util.h>
-#include <base/location.h>
 #include <base/logging.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
-#include <base/time/time.h>
 #include <chromeos/flag_helper.h>
-#include <chromeos/message_loops/glib_message_loop.h>
+#include <chromeos/message_loops/base_message_loop.h>
 #include <glib.h>
 #include <metrics/metrics_library.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "update_engine/certificate_checker.h"
-#include "update_engine/dbus_constants.h"
-#include "update_engine/dbus_service.h"
-#include "update_engine/dbus_wrapper_interface.h"
+#include "update_engine/daemon.h"
 #include "update_engine/glib_utils.h"
-#include "update_engine/real_system_state.h"
-#include "update_engine/subprocess.h"
 #include "update_engine/terminator.h"
-#include "update_engine/update_attempter.h"
-extern "C" {
-#include "update_engine/org.chromium.UpdateEngineInterface.dbusserver.h"
-}
 #include "update_engine/utils.h"
 
 using std::string;
-using std::vector;
-
-namespace {
-const int kDBusSystemMaxWaitSeconds = 2 * 60;
-}  // namespace
 
 namespace chromeos_update_engine {
-
 namespace {
 
-// Wait for DBus to be ready by attempting to get the system bus up to
-// |timeout| time. Returns whether it succeeded to get the bus.
-bool WaitForDBusSystem(base::TimeDelta timeout) {
-  GError *error = nullptr;
-  DBusGConnection *bus = nullptr;
-  Clock clock;
-  base::Time deadline = clock.GetMonotonicTime() + timeout;
-
-  while (clock.GetMonotonicTime() < deadline) {
-    bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-    if (bus)
-      return true;
-    LOG(WARNING) << "Failed to get system bus, waiting: "
-                 << utils::GetAndFreeGError(&error);
-    // Wait 1 second.
-    sleep(1);
-  }
-  LOG(ERROR) << "Failed to get system bus after " << timeout.InSeconds()
-             << " seconds.";
-  return false;
-}
-
-void SetupDBusService(UpdateEngineService* service) {
-  DBusGConnection *bus;
-  DBusGProxy *proxy;
-  GError *error = nullptr;
-
-  bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-  LOG_IF(FATAL, !bus) << "Failed to get bus: "
-                      << utils::GetAndFreeGError(&error);
-  proxy = dbus_g_proxy_new_for_name(bus,
-                                    DBUS_SERVICE_DBUS,
-                                    DBUS_PATH_DBUS,
-                                    DBUS_INTERFACE_DBUS);
-  guint32 request_name_ret;
-  if (!org_freedesktop_DBus_request_name(proxy,
-                                         kUpdateEngineServiceName,
-                                         0,
-                                         &request_name_ret,
-                                         &error)) {
-    LOG(FATAL) << "Failed to get name: " << utils::GetAndFreeGError(&error);
-  }
-  if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-    g_warning("Got result code %u from requesting name", request_name_ret);
-    LOG(FATAL) << "Got result code " << request_name_ret
-               << " from requesting name, but expected "
-               << DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
-  }
-  dbus_g_connection_register_g_object(bus,
-                                      "/org/chromium/UpdateEngine",
-                                      G_OBJECT(service));
-}
-
 void SetupLogSymlink(const string& symlink_path, const string& log_path) {
   // TODO(petkov): To ensure a smooth transition between non-timestamped and
   // timestamped logs, move an existing log to start the first timestamped
@@ -168,7 +97,6 @@
 
   ::g_type_init();
   dbus_threads_init_default();
-  base::AtExitManager exit_manager;  // Required for base/rand_util.h.
   chromeos_update_engine::Terminator::Init();
   chromeos::FlagHelper::Init(argc, argv, "Chromium OS Update Engine");
   chromeos_update_engine::SetupLogging(FLAGS_logtostderr);
@@ -183,74 +111,10 @@
   // Done _after_ log file creation.
   umask(S_IXUSR | S_IRWXG | S_IRWXO);
 
-  // Create the single Glib main loop. Code accessing directly the glib main
-  // loop (such as calling g_timeout_add() or similar functions) will still work
-  // since the backend for the message loop is still the Glib main loop.
-  // TODO(deymo): Replace this |loop| with one based on libevent once no other
-  // code here uses glib directly.
-  chromeos::GlibMessageLoop loop;
-  loop.SetAsCurrent();
+  chromeos_update_engine::UpdateEngineDaemon update_engine_daemon;
+  int exit_code = update_engine_daemon.Run();
 
-  // The Subprocess class requires a chromeos::MessageLoop setup.
-  chromeos_update_engine::Subprocess subprocess;
-  subprocess.Init();
-
-  // Wait up to 2 minutes for DBus to be ready.
-  LOG_IF(FATAL, !chromeos_update_engine::WaitForDBusSystem(
-      base::TimeDelta::FromSeconds(kDBusSystemMaxWaitSeconds)))
-      << "Failed to initialize DBus, aborting.";
-
-  chromeos_update_engine::RealSystemState real_system_state;
-  LOG_IF(ERROR, !real_system_state.Initialize())
-      << "Failed to initialize system state.";
-  chromeos_update_engine::UpdateAttempter *update_attempter =
-      real_system_state.update_attempter();
-  CHECK(update_attempter);
-
-  // Sets static members for the certificate checker.
-  chromeos_update_engine::CertificateChecker::set_system_state(
-      &real_system_state);
-  chromeos_update_engine::OpenSSLWrapper openssl_wrapper;
-  chromeos_update_engine::CertificateChecker::set_openssl_wrapper(
-      &openssl_wrapper);
-
-  // Create the dbus service object:
-  dbus_g_object_type_install_info(UPDATE_ENGINE_TYPE_SERVICE,
-                                  &dbus_glib_update_engine_service_object_info);
-  UpdateEngineService* service = update_engine_service_new();
-  service->system_state_ = &real_system_state;
-  update_attempter->set_dbus_service(service);
-  chromeos_update_engine::SetupDBusService(service);
-
-  // Initiate update checks.
-  update_attempter->ScheduleUpdates();
-
-  // Update boot flags after 45 seconds.
-  loop.PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&chromeos_update_engine::UpdateAttempter::UpdateBootFlags,
-                 base::Unretained(update_attempter)),
-      base::TimeDelta::FromSeconds(45));
-
-  // Broadcast the update engine status on startup to ensure consistent system
-  // state on crashes.
-  loop.PostTask(FROM_HERE, base::Bind(
-      &chromeos_update_engine::UpdateAttempter::BroadcastStatus,
-      base::Unretained(update_attempter)));
-
-  // Run the UpdateEngineStarted() method on |update_attempter|.
-  loop.PostTask(FROM_HERE, base::Bind(
-      &chromeos_update_engine::UpdateAttempter::UpdateEngineStarted,
-      base::Unretained(update_attempter)));
-
-  // Run the main loop until exit time:
-  loop.Run();
-
-  // Cleanup:
-  update_attempter->set_dbus_service(nullptr);
-  g_object_unref(G_OBJECT(service));
-
-  loop.ReleaseFromCurrent();
-  LOG(INFO) << "Chrome OS Update Engine terminating";
-  return 0;
+  LOG(INFO) << "Chrome OS Update Engine terminating with exit code "
+            << exit_code;
+  return exit_code;
 }
diff --git a/p2p_manager_unittest.cc b/p2p_manager_unittest.cc
index ec93bc6..3b1f1c0 100644
--- a/p2p_manager_unittest.cc
+++ b/p2p_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include <base/callback.h>
 #include <base/files/file_util.h>
 #include <base/strings/stringprintf.h>
+#include <chromeos/asynchronous_signal_handler.h>
 #include <chromeos/message_loops/glib_message_loop.h>
 #include <chromeos/message_loops/message_loop.h>
 #include <chromeos/message_loops/message_loop_utils.h>
@@ -57,7 +58,8 @@
   // Derived from testing::Test.
   void SetUp() override {
     loop_.SetAsCurrent();
-    subprocess_.Init();
+    async_signal_handler_.Init();
+    subprocess_.Init(&async_signal_handler_);
     test_conf_ = new FakeP2PManagerConfiguration();
 
     // Allocate and install a mock policy implementation in the fake Update
@@ -76,6 +78,7 @@
   // interact with the p2p-client tool, so we need to run a GlibMessageLoop
   // here.
   chromeos::GlibMessageLoop loop_;
+  chromeos::AsynchronousSignalHandler async_signal_handler_;
   Subprocess subprocess_;
 
   // The P2PManager::Configuration instance used for testing.
diff --git a/postinstall_runner_action_unittest.cc b/postinstall_runner_action_unittest.cc
index ff64128..5131239 100644
--- a/postinstall_runner_action_unittest.cc
+++ b/postinstall_runner_action_unittest.cc
@@ -37,7 +37,8 @@
  protected:
   void SetUp() override {
     loop_.SetAsCurrent();
-    subprocess_.Init();
+    async_signal_handler_.Init();
+    subprocess_.Init(&async_signal_handler_);
   }
 
   // DoTest with various combinations of do_losetup, err_code and
@@ -48,6 +49,7 @@
   static const char* kImageMountPointTemplate;
 
   chromeos::GlibMessageLoop loop_;
+  chromeos::AsynchronousSignalHandler async_signal_handler_;
   Subprocess subprocess_;
 };
 
diff --git a/subprocess.cc b/subprocess.cc
index 6282b2c..fa7e4cb 100644
--- a/subprocess.cc
+++ b/subprocess.cc
@@ -80,14 +80,14 @@
 
 }  // namespace
 
-void Subprocess::Init() {
+void Subprocess::Init(
+      chromeos::AsynchronousSignalHandlerInterface* async_signal_handler) {
   if (subprocess_singleton_ == this)
     return;
   CHECK(subprocess_singleton_ == nullptr);
   subprocess_singleton_ = this;
 
-  async_signal_handler_.Init();
-  process_reaper_.Register(&async_signal_handler_);
+  process_reaper_.Register(async_signal_handler);
 }
 
 Subprocess::~Subprocess() {
diff --git a/subprocess.h b/subprocess.h
index c26ea60..775b95f 100644
--- a/subprocess.h
+++ b/subprocess.h
@@ -15,7 +15,7 @@
 #include <base/callback.h>
 #include <base/logging.h>
 #include <base/macros.h>
-#include <chromeos/asynchronous_signal_handler.h>
+#include <chromeos/asynchronous_signal_handler_interface.h>
 #include <chromeos/message_loops/message_loop.h>
 #include <chromeos/process.h>
 #include <chromeos/process_reaper.h>
@@ -49,7 +49,7 @@
   ~Subprocess();
 
   // Initialize and register the Subprocess singleton.
-  void Init();
+  void Init(chromeos::AsynchronousSignalHandlerInterface* async_signal_handler);
 
   // Launches a process in the background and calls the passed |callback| when
   // the process exits.
@@ -119,7 +119,6 @@
   std::map<pid_t, std::unique_ptr<SubprocessRecord>> subprocess_records_;
 
   // Used to watch for child processes.
-  chromeos::AsynchronousSignalHandler async_signal_handler_;
   chromeos::ProcessReaper process_reaper_;
 
   DISALLOW_COPY_AND_ASSIGN(Subprocess);
diff --git a/subprocess_unittest.cc b/subprocess_unittest.cc
index 2660456..3933f25 100644
--- a/subprocess_unittest.cc
+++ b/subprocess_unittest.cc
@@ -43,12 +43,14 @@
  protected:
   void SetUp() override {
     loop_.SetAsCurrent();
-    subprocess_.Init();
+    async_signal_handler_.Init();
+    subprocess_.Init(&async_signal_handler_);
   }
 
   // TODO(deymo): Replace this with a FakeMessageLoop. Subprocess uses glib to
   // asynchronously spawn a process, so we need to run a GlibMessageLoop here.
   chromeos::GlibMessageLoop loop_;
+  chromeos::AsynchronousSignalHandler async_signal_handler_;
   Subprocess subprocess_;
 };
 
diff --git a/update_attempter.cc b/update_attempter.cc
index 3afe2ac..762a7e5 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -1243,12 +1243,10 @@
 }
 
 void UpdateAttempter::BroadcastStatus() {
-  if (!dbus_service_) {
+  if (!dbus_adaptor_)
     return;
-  }
   last_notify_time_ = TimeTicks::Now();
-  update_engine_service_emit_status_update(
-      dbus_service_,
+  dbus_adaptor_->SendStatusUpdateSignal(
       last_checked_time_,
       download_progress_,
       UpdateStatusToString(status_),
diff --git a/update_attempter.h b/update_attempter.h
index 48d344f..ea32fe4 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -28,7 +28,6 @@
 #include "update_engine/update_manager/update_manager.h"
 
 class MetricsLibraryInterface;
-struct UpdateEngineService;
 
 namespace policy {
 class PolicyProvider;
@@ -36,6 +35,7 @@
 
 namespace chromeos_update_engine {
 
+class UpdateEngineAdaptor;
 class DBusWrapperInterface;
 
 enum UpdateStatus {
@@ -119,8 +119,8 @@
   int http_response_code() const { return http_response_code_; }
   void set_http_response_code(int code) { http_response_code_ = code; }
 
-  void set_dbus_service(struct UpdateEngineService* dbus_service) {
-    dbus_service_ = dbus_service;
+  void set_dbus_adaptor(UpdateEngineAdaptor* dbus_adaptor) {
+    dbus_adaptor_ = dbus_adaptor;
   }
 
   // This is the internal entry point for going through an
@@ -400,7 +400,7 @@
 
   // If non-null, this UpdateAttempter will send status updates over this
   // dbus service.
-  UpdateEngineService* dbus_service_ = nullptr;
+  UpdateEngineAdaptor* dbus_adaptor_ = nullptr;
 
   // Pointer to the OmahaResponseHandlerAction in the actions_ vector.
   std::shared_ptr<OmahaResponseHandlerAction> response_handler_action_;
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 07ba451..941f2b2 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -116,7 +116,7 @@
   void SetUp() override {
     CHECK(utils::MakeTempDirectory("UpdateAttempterTest-XXXXXX", &test_dir_));
 
-    EXPECT_EQ(nullptr, attempter_.dbus_service_);
+    EXPECT_EQ(nullptr, attempter_.dbus_adaptor_);
     EXPECT_NE(nullptr, attempter_.system_state_);
     EXPECT_EQ(0, attempter_.http_response_code_);
     EXPECT_EQ(utils::kCpuSharesNormal, attempter_.shares_);
diff --git a/update_engine.gyp b/update_engine.gyp
index f377500..1ddb4d9 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -59,19 +59,17 @@
       ],
       'includes': ['../common-mk/protoc.gypi'],
     },
-    # D-Bus glib bindings.
+    # Chrome D-Bus bindings.
     {
-      'target_name': 'update_engine-dbus-server',
+      'target_name': 'update_engine-dbus-adaptor',
       'type': 'none',
       'variables': {
-        'dbus_glib_type': 'server',
-        'dbus_glib_out_dir': 'include/update_engine',
-        'dbus_glib_prefix': 'update_engine_service',
+        'dbus_adaptors_out_dir': 'include/update_engine/dbus_adaptor',
       },
       'sources': [
         'dbus_bindings/org.chromium.UpdateEngineInterface.xml',
       ],
-      'includes': ['../common-mk/dbus_glib.gypi'],
+      'includes': ['../common-mk/generate-dbus-adaptors.gypi'],
     },
     # The main static_library with all the code.
     {
@@ -125,6 +123,7 @@
         'clock.cc',
         'connection_manager.cc',
         'constants.cc',
+        'daemon.cc',
         'dbus_service.cc',
         'delta_performer.cc',
         'download_action.cc',
@@ -191,7 +190,7 @@
       'type': 'executable',
       'dependencies': [
         'libupdate_engine',
-        'update_engine-dbus-server',
+        'update_engine-dbus-adaptor',
       ],
       'sources': [
         'main.cc',
@@ -369,6 +368,7 @@
             'certificate_checker_unittest.cc',
             'chrome_browser_proxy_resolver_unittest.cc',
             'connection_manager_unittest.cc',
+            'dbus_service_unittest.cc',
             'delta_performer_unittest.cc',
             'download_action_unittest.cc',
             'extent_writer_unittest.cc',