update_engine: Switch to chrome-dbus for client requests in update_engine

update_engine daemon acts as DBus client to send DBus calls to shill,
power_manager and chrome, and to listen for signals from shill, chrome
and login_manager. This patch migrates these calls and signals to use
chrome-dbus framework instead of dbus-glib.

All references to dbus-glib code are removed.

BUG=chromium:419827
TEST=Updated unittest. Deployed on a link device and tested interactions with shill and chromium.

Change-Id: I31b389e0d1690cccb115ff3b6539c876ba81bd0e
Reviewed-on: https://chromium-review.googlesource.com/290990
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Trybot-Ready: Alex Deymo <deymo@chromium.org>
diff --git a/connection_manager.cc b/connection_manager.cc
index 45b6467..d0d3392 100644
--- a/connection_manager.cc
+++ b/connection_manager.cc
@@ -10,7 +10,6 @@
 #include <base/stl_util.h>
 #include <base/strings/string_util.h>
 #include <chromeos/dbus/service_constants.h>
-#include <dbus/dbus-glib.h>
 #include <glib.h>
 #include <policy/device_policy.h>
 
@@ -18,6 +17,8 @@
 #include "update_engine/system_state.h"
 #include "update_engine/utils.h"
 
+using org::chromium::flimflam::ManagerProxyInterface;
+using org::chromium::flimflam::ServiceProxyInterface;
 using std::set;
 using std::string;
 
@@ -25,163 +26,38 @@
 
 namespace {
 
-// Gets the DbusGProxy for FlimFlam. Must be free'd with ProxyUnref()
-bool GetFlimFlamProxy(DBusWrapperInterface* dbus_iface,
-                      const char* path,
-                      const char* interface,
-                      DBusGProxy** out_proxy) {
-  DBusGConnection* bus;
-  DBusGProxy* proxy;
-  GError* error = nullptr;
-
-  bus = dbus_iface->BusGet(DBUS_BUS_SYSTEM, &error);
-  if (!bus) {
-    LOG(ERROR) << "Failed to get system bus";
-    return false;
-  }
-  proxy = dbus_iface->ProxyNewForName(bus, shill::kFlimflamServiceName, path,
-                                      interface);
-  *out_proxy = proxy;
-  return true;
-}
-
-// On success, caller owns the GHashTable at out_hash_table.
-// Returns true on success.
-bool GetProperties(DBusWrapperInterface* dbus_iface,
-                   const char* path,
-                   const char* interface,
-                   GHashTable** out_hash_table) {
-  DBusGProxy* proxy;
-  GError* error = nullptr;
-
-  TEST_AND_RETURN_FALSE(GetFlimFlamProxy(dbus_iface,
-                                         path,
-                                         interface,
-                                         &proxy));
-
-  gboolean rc = dbus_iface->ProxyCall_0_1(proxy,
-                                          "GetProperties",
-                                          &error,
-                                          out_hash_table);
-  dbus_iface->ProxyUnref(proxy);
-  if (rc == FALSE) {
-    LOG(ERROR) << "dbus_g_proxy_call failed";
-    return false;
-  }
-
-  return true;
-}
-
-// Returns (via out_path) the default network path, or empty string if
-// there's no network up.
-// Returns true on success.
-bool GetDefaultServicePath(DBusWrapperInterface* dbus_iface, string* out_path) {
-  GHashTable* hash_table = nullptr;
-
-  TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
-                                      shill::kFlimflamServicePath,
-                                      shill::kFlimflamManagerInterface,
-                                      &hash_table));
-
-  GValue* value = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
-                                                                "Services"));
-  GPtrArray* array = nullptr;
-  bool success = false;
-  if (G_VALUE_HOLDS(value, DBUS_TYPE_G_OBJECT_PATH_ARRAY) &&
-      (array = reinterpret_cast<GPtrArray*>(g_value_get_boxed(value))) &&
-      (array->len > 0)) {
-    *out_path = static_cast<const char*>(g_ptr_array_index(array, 0));
-    success = true;
-  }
-
-  g_hash_table_unref(hash_table);
-  return success;
-}
-
-NetworkConnectionType ParseConnectionType(const char* type_str) {
-  if (!strcmp(type_str, shill::kTypeEthernet)) {
+NetworkConnectionType ParseConnectionType(const string& type_str) {
+  if (type_str == shill::kTypeEthernet) {
     return NetworkConnectionType::kEthernet;
-  } else if (!strcmp(type_str, shill::kTypeWifi)) {
+  } else if (type_str == shill::kTypeWifi) {
     return NetworkConnectionType::kWifi;
-  } else if (!strcmp(type_str, shill::kTypeWimax)) {
+  } else if (type_str == shill::kTypeWimax) {
     return NetworkConnectionType::kWimax;
-  } else if (!strcmp(type_str, shill::kTypeBluetooth)) {
+  } else if (type_str == shill::kTypeBluetooth) {
     return NetworkConnectionType::kBluetooth;
-  } else if (!strcmp(type_str, shill::kTypeCellular)) {
+  } else if (type_str == shill::kTypeCellular) {
     return NetworkConnectionType::kCellular;
   }
   return NetworkConnectionType::kUnknown;
 }
 
-NetworkTethering ParseTethering(const char* tethering_str) {
-  if (!strcmp(tethering_str, shill::kTetheringNotDetectedState)) {
+NetworkTethering ParseTethering(const string& tethering_str) {
+  if (tethering_str == shill::kTetheringNotDetectedState) {
     return NetworkTethering::kNotDetected;
-  } else if (!strcmp(tethering_str, shill::kTetheringSuspectedState)) {
+  } else if (tethering_str == shill::kTetheringSuspectedState) {
     return NetworkTethering::kSuspected;
-  } else if (!strcmp(tethering_str, shill::kTetheringConfirmedState)) {
+  } else if (tethering_str == shill::kTetheringConfirmedState) {
     return NetworkTethering::kConfirmed;
   }
   LOG(WARNING) << "Unknown Tethering value: " << tethering_str;
   return NetworkTethering::kUnknown;
 }
 
-bool GetServicePathProperties(DBusWrapperInterface* dbus_iface,
-                              const string& path,
-                              NetworkConnectionType* out_type,
-                              NetworkTethering* out_tethering) {
-  GHashTable* hash_table = nullptr;
-
-  TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
-                                      path.c_str(),
-                                      shill::kFlimflamServiceInterface,
-                                      &hash_table));
-
-  // Populate the out_tethering.
-  GValue* value =
-      reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
-                                                    shill::kTetheringProperty));
-  const char* tethering_str = nullptr;
-
-  if (value != nullptr)
-    tethering_str = g_value_get_string(value);
-  if (tethering_str != nullptr) {
-    *out_tethering = ParseTethering(tethering_str);
-  } else {
-    // Set to Unknown if not present.
-    *out_tethering = NetworkTethering::kUnknown;
-  }
-
-  // Populate the out_type property.
-  value = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
-                                                        shill::kTypeProperty));
-  const char* type_str = nullptr;
-  bool success = false;
-  if (value != nullptr && (type_str = g_value_get_string(value)) != nullptr) {
-    success = true;
-    if (!strcmp(type_str, shill::kTypeVPN)) {
-      value = reinterpret_cast<GValue*>(
-          g_hash_table_lookup(hash_table, shill::kPhysicalTechnologyProperty));
-      if (value != nullptr &&
-          (type_str = g_value_get_string(value)) != nullptr) {
-        *out_type = ParseConnectionType(type_str);
-      } else {
-        LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
-                   << " connection (service: " << path << "). Returning default"
-                   << " NetworkConnectionType::kUnknown value.";
-        *out_type = NetworkConnectionType::kUnknown;
-      }
-    } else {
-      *out_type = ParseConnectionType(type_str);
-    }
-  }
-  g_hash_table_unref(hash_table);
-  return success;
-}
-
 }  // namespace
 
-ConnectionManager::ConnectionManager(SystemState *system_state)
-    :  system_state_(system_state) {}
+ConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
+                                     SystemState* system_state)
+    : shill_proxy_(shill_proxy), system_state_(system_state) {}
 
 bool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type,
                                             NetworkTethering tethering) const {
@@ -273,33 +149,81 @@
   return "Unknown";
 }
 
-// static
-const char* ConnectionManager::StringForTethering(NetworkTethering tethering) {
-  switch (tethering) {
-    case NetworkTethering::kNotDetected:
-      return shill::kTetheringNotDetectedState;
-    case NetworkTethering::kSuspected:
-      return shill::kTetheringSuspectedState;
-    case NetworkTethering::kConfirmed:
-      return shill::kTetheringConfirmedState;
-    case NetworkTethering::kUnknown:
-      return "Unknown";
-  }
-  // The program shouldn't reach this point, but the compiler isn't smart
-  // enough to infer that.
-  return "Unknown";
+bool ConnectionManager::GetConnectionProperties(
+    NetworkConnectionType* out_type,
+    NetworkTethering* out_tethering) {
+  string default_service_path;
+  TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
+  if (default_service_path.empty())
+    return false;
+  TEST_AND_RETURN_FALSE(
+      GetServicePathProperties(default_service_path, out_type, out_tethering));
+  return true;
 }
 
-bool ConnectionManager::GetConnectionProperties(
-    DBusWrapperInterface* dbus_iface,
+bool ConnectionManager::GetDefaultServicePath(string* out_path) {
+  chromeos::VariantDictionary properties;
+  chromeos::ErrorPtr error;
+  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
+  if (!manager_proxy)
+    return false;
+  TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));
+
+  const auto& prop_default_service =
+      properties.find(shill::kDefaultServiceProperty);
+  if (prop_default_service == properties.end())
+    return false;
+
+  *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>().value();
+  return !out_path->empty();
+}
+
+bool ConnectionManager::GetServicePathProperties(
+    const string& path,
     NetworkConnectionType* out_type,
-    NetworkTethering* out_tethering) const {
-  string default_service_path;
-  TEST_AND_RETURN_FALSE(GetDefaultServicePath(dbus_iface,
-                                              &default_service_path));
-  TEST_AND_RETURN_FALSE(GetServicePathProperties(dbus_iface,
-                                                 default_service_path,
-                                                 out_type, out_tethering));
+    NetworkTethering* out_tethering) {
+  // We create and dispose the ServiceProxyInterface on every request.
+  std::unique_ptr<ServiceProxyInterface> service =
+      shill_proxy_->GetServiceForPath(path);
+
+  chromeos::VariantDictionary properties;
+  chromeos::ErrorPtr error;
+  TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));
+
+  // Populate the out_tethering.
+  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
+  if (prop_tethering == properties.end()) {
+    // Set to Unknown if not present.
+    *out_tethering = NetworkTethering::kUnknown;
+  } else {
+    // If the property doesn't contain a string value, the empty string will
+    // become kUnknown.
+    *out_tethering = ParseTethering(prop_tethering->second.TryGet<string>());
+  }
+
+  // Populate the out_type property.
+  const auto& prop_type = properties.find(shill::kTypeProperty);
+  if (prop_type == properties.end()) {
+    // Set to Unknown if not present.
+    *out_type = NetworkConnectionType::kUnknown;
+    return false;
+  }
+
+  string type_str = prop_type->second.TryGet<string>();
+  if (type_str == shill::kTypeVPN) {
+    const auto& prop_physical =
+        properties.find(shill::kPhysicalTechnologyProperty);
+    if (prop_physical == properties.end()) {
+      LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
+                 << " connection (service: " << path << "). Returning default"
+                 << " kUnknown value.";
+      *out_type = NetworkConnectionType::kUnknown;
+    } else {
+      *out_type = ParseConnectionType(prop_physical->second.TryGet<string>());
+    }
+  } else {
+    *out_type = ParseConnectionType(type_str);
+  }
   return true;
 }