Skip mount if zip path doesn't exist
[platform/core/appfw/app-installers.git] / src / common / tzip_interface.cc
index 8a5736e..26fabf2 100644 (file)
@@ -8,9 +8,11 @@
 
 #include <boost/filesystem.hpp>
 
-#include <dbus/dbus.h>
+#include <gio/gio.h>
+#include <glib.h>
 
 #include <cstdlib>
+#include <functional>
 
 namespace bf = boost::filesystem;
 
@@ -27,43 +29,79 @@ const int kTzipMountMaximumRetryCount = 15;
 
 }  // namespace
 
-void DBusMessageDeleter(DBusMessage* message) {
-  dbus_message_unref(message);
-}
+namespace common_installer {
 
-void DBusErrorDeleter(DBusError* error) {
-  dbus_error_free(error);
-  std::default_delete<DBusError>();
-}
+class DBusProxy {
+ public:
+  DBusProxy() : conn_(nullptr), proxy_(nullptr) {
+    if (!Init())
+      LOG(ERROR) << "Failed to initialize DBus proxy";
+  }
 
-namespace common_installer {
+  ~DBusProxy() {
+    if (proxy_)
+      g_object_unref(proxy_);
+    if (conn_) {
+      g_dbus_connection_flush_sync(conn_, nullptr, nullptr);
+      g_object_unref(conn_);
+    }
+  }
+
+  bool Init() {
+    GError* error = nullptr;
+    conn_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+    if (!conn_ || error) {
+      LOG(ERROR) << "g_bus_get_sync() failed: " << error->message;
+      g_error_free(error);
+      return false;
+    }
+    proxy_ = g_dbus_proxy_new_sync(conn_, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+        kTzipBusName, kTzipObjectPath, kTzipInterfaceName, nullptr, &error);
+    if (!proxy_ || error) {
+      LOG(ERROR) << "g_dbus_proxy_new_sync() failed: " << error->message;
+      g_error_free(error);
+      return false;
+    }
+    return true;
+  }
+
+  GVariant* ProxyCallSync(const char* method, GVariant* params) {
+    if (!proxy_) {
+      LOG(ERROR) << "DBus proxy is not initialized";
+      return nullptr;
+    }
+    GError* error = nullptr;
+    GVariant* ret = g_dbus_proxy_call_sync(proxy_, method,
+        params, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
+    if (error) {
+      LOG(ERROR) << "g_dbus_proxy_call_sync() of " << method << " failed: "
+                 << error->message;
+      g_error_free(error);
+    }
+    return ret;
+  }
+
+ private:
+  GDBusConnection* conn_;
+  GDBusProxy* proxy_;
+};
 
 class TzipInterface::Pimpl {
  public:
   explicit Pimpl(const boost::filesystem::path& mount_path) :
-    mount_path_(mount_path) { }
+    mount_path_(mount_path), dbus_proxy_(new DBusProxy()) { }
 
   bool MountZip(const boost::filesystem::path& zip_path) {
     zip_path_ = zip_path;
 
-    DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
-    if (!conn) {
-      return false;
-    }
-
     if (bf::exists(mount_path_)) {
       LOG(WARNING) << "Mount path(" << mount_path_ << ") already exists! "
                    << "We will remove it...";
       bf::remove(mount_path_);
     }
 
-    std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
-        dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
-                                     kTzipInterfaceName,
-                                     kTzipMountMethod),
-                                     DBusMessageDeleter);
-    if (!msg) {
-      LOG(ERROR) << "Could not create new dbus message";
+    if (!bf::exists(zip_path)) {
+      LOG(WARNING) << "zip path(" << zip_path << ") doesn't exist!";
       return false;
     }
 
@@ -71,103 +109,64 @@ class TzipInterface::Pimpl {
     const char* zip_path_str = zip_path_.string().c_str();
     const char* tzip_smack_rule = kTzipSmackRule;
 
-    if (!dbus_message_append_args(msg.get(),
-            DBUS_TYPE_STRING, &mount_path_str,
-            DBUS_TYPE_STRING, &zip_path_str,
-            DBUS_TYPE_STRING, &tzip_smack_rule,
-            DBUS_TYPE_INVALID)) {
-      return false;
-    }
-
-    if (dbus_connection_send(conn, msg.get(), nullptr) == FALSE) {
+    GVariant* r = dbus_proxy_->ProxyCallSync(kTzipMountMethod,
+        g_variant_new("(sss)", mount_path_str, zip_path_str, tzip_smack_rule));
+    if (!r) {
       LOG(ERROR) << "Could not send DBUS message when mounting zip file";
       return false;
     }
-    return WaitForMounted();
+    g_variant_unref(r);
+
+    return WaitForCondition([=](bool *success)->bool {
+      return IsMounted(success);
+    });
   }
 
   bool UnmountZip() {
-    DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
-    if (!conn) {
-      return false;
-    }
-
-    std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
-        dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
-                                     kTzipInterfaceName,
-                                     kTzipUnmountMethod),
-                                     DBusMessageDeleter);
-    if (!msg) {
-      LOG(ERROR) << "Could not create new dbus message";
-      return false;
-    }
-
     const char* mount_path_str = mount_path_.string().c_str();
-    if (!dbus_message_append_args(msg.get(),
-            DBUS_TYPE_STRING, &mount_path_str,
-            DBUS_TYPE_INVALID)) {
-      return false;
-    }
 
-    if (dbus_connection_send(conn, msg.get(), nullptr) == FALSE) {
+    GVariant* r = dbus_proxy_->ProxyCallSync(kTzipUnmountMethod,
+        g_variant_new("(s)", mount_path_str));
+    if (!r) {
       LOG(ERROR) << "Could not send DBUS message when unmounting zip file";
       return false;
     }
+    g_variant_unref(r);
 
-    return true;
+    return WaitForCondition([=](bool *success)->bool {
+      return IsUnmounted(success);
+    });
   }
 
  private:
-  bool IsMounted() {
-    int ret = -1;
-    int r = -1;
-    DBusMessage *reply;
-    std::unique_ptr<DBusError, void(*)(DBusError*)> err(new DBusError(),
-                                                        DBusErrorDeleter);
-
-    DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
-    if (!conn) {
-      return false;
-    }
-    std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
-        dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
-                                     kTzipInterfaceName,
-                                     kTzipIsMountedMethod),
-                                     DBusMessageDeleter);
-    if (!msg) {
-      return false;
-    }
-
+  bool IsMounted(bool *success) {
     const char* mount_path_str = mount_path_.string().c_str();
-    if (!dbus_message_append_args(msg.get(),
-            DBUS_TYPE_STRING, &mount_path_str,
-            DBUS_TYPE_INVALID)) {
-      return false;
-    }
-
-    dbus_error_init(err.get());
-    reply = dbus_connection_send_with_reply_and_block(conn, msg.get(), 500,
-                                                      err.get());
-    if (!reply) {
-      return false;
-    }
-
-    r = dbus_message_get_args(reply, err.get(), DBUS_TYPE_INT32, &ret,
-                              DBUS_TYPE_INVALID);
+    GVariant* r = dbus_proxy_->ProxyCallSync(kTzipIsMountedMethod,
+        g_variant_new("(s)", mount_path_str));
     if (!r) {
+      *success = false;
       return false;
     }
 
+    gint ret;
+    g_variant_get(r, "(i)", &ret);
+    g_variant_unref(r);
+    *success = true;
     return ret != 0;
   }
 
-  bool WaitForMounted() {
+  bool IsUnmounted(bool *success) {
+    return !IsMounted(success);
+  }
+
+  bool WaitForCondition(std::function<bool(bool*)> condition) {
     if (!mount_path_.empty()) {
       bool rv = false;
       int cnt = 0;
       while (cnt < kTzipMountMaximumRetryCount) {
-        rv = IsMounted();
-        if (rv)
+        bool success;
+        rv = condition(&success);
+        if (rv && success)
           break;
         sleep(1);
         cnt++;
@@ -182,9 +181,9 @@ class TzipInterface::Pimpl {
 
   boost::filesystem::path mount_path_;
   boost::filesystem::path zip_path_;
+  std::unique_ptr<DBusProxy> dbus_proxy_;
 };
 
-
 TzipInterface::TzipInterface(const boost::filesystem::path& mount_path)
   : impl_(new Pimpl(mount_path)) {}