Add new apis for remote package information
authorInkyun Kil <inkyun.kil@samsung.com>
Thu, 12 Jul 2018 02:18:48 +0000 (11:18 +0900)
committer장상윤/Tizen Platform Lab(SR)/Engineer/삼성전자 <jeremy.jang@samsung.com>
Thu, 26 Jul 2018 07:10:29 +0000 (16:10 +0900)
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
src/client/client.cc
src/client/include/capmgr.h
src/common/db_manager.cc
src/common/db_manager.h
src/common/remote_package_info.h [new file with mode: 0644]
src/unit_tests/smoke_test.cc

index 863fc9f66d4c72b5aac94cbbafbb5456f46f2002..a79a3cf3dba7912cf3d0b3bbf0df494429d9214c 100644 (file)
@@ -11,6 +11,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "client/dbus.h"
 #include "client/include/capmgr.h"
@@ -42,6 +43,13 @@ struct capmgr_app_control_s {
   bundle* b;
 };
 
+struct capmgr_package_info_s {
+  std::string pkgid;
+  std::string label;
+  std::string version;
+  std::vector<std::string> appid_list;
+};
+
 API int capmgr_device_foreach_devices(capmgr_device_foreach_cb cb,
     void* user_data) {
   if (!cb)
@@ -462,3 +470,99 @@ API int capmgr_app_control_send(capmgr_app_control_h app_control) {
 
   return CAPMGR_ERROR_NONE;
 }
+
+API int capmgr_package_info_get_pkgid(capmgr_package_info_h remote_package_info,
+    char** pkgid) {
+  if (!remote_package_info || !pkgid ||
+      remote_package_info->pkgid.empty())
+    return CAPMGR_ERROR_INVALID_PARAMETER;
+
+  *pkgid = strdup(remote_package_info->pkgid.c_str());
+  if (*pkgid == nullptr)
+    return CAPMGR_ERROR_OUT_OF_MEMORY;
+
+  return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_package_info_get_label(capmgr_package_info_h remote_package_info,
+    char** label) {
+  if (!remote_package_info || !label ||
+      remote_package_info->label.empty())
+    return CAPMGR_ERROR_INVALID_PARAMETER;
+
+  *label = strdup(remote_package_info->label.c_str());
+  if (*label == nullptr)
+    return CAPMGR_ERROR_OUT_OF_MEMORY;
+
+  return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_package_info_get_version(
+    capmgr_package_info_h remote_package_info, char** version) {
+  if (!remote_package_info || !version ||
+      remote_package_info->version.empty())
+    return CAPMGR_ERROR_INVALID_PARAMETER;
+
+  *version = strdup(remote_package_info->version.c_str());
+  if (*version == nullptr)
+    return CAPMGR_ERROR_OUT_OF_MEMORY;
+
+  return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_package_info_foreach_packages(const capmgr_device_h device,
+    capmgr_package_info_foreach_package_cb cb,
+    void* user_data) {
+  std::map<std::string, capmgr_package_info_s> pkg_map;
+
+  if (!cb)
+    return CAPMGR_ERROR_INVALID_PARAMETER;
+
+  std::unique_ptr<capmgr::SQLConnection> sql_conn(
+      new capmgr::SQLiteConnection(kDBPath, true));
+
+  const char kQueryForeachPackages[] =
+      "SELECT appid, pkgid, label, version FROM remote_app_info WHERE "
+      "device_id = ?";
+
+  std::shared_ptr<capmgr::SQLStatement> stmt = sql_conn->PrepareStatement(
+      kQueryForeachPackages);
+  if (stmt->BindString(1, device->device_id)) {
+    while (stmt->Step() == capmgr::SQLStatement::StepResult::ROW) {
+      struct capmgr_package_info_s info;
+      std::string appid;
+      int idx = 0;
+      appid = stmt->GetColumnString(idx++);
+      info.pkgid = stmt->GetColumnString(idx++);
+      info.label = stmt->GetColumnString(idx++);
+      info.version = stmt->GetColumnString(idx++);
+
+      auto search_info = pkg_map.find(appid);
+      if (search_info != pkg_map.end()) {
+        info.appid_list.emplace_back(appid);
+        pkg_map.emplace(appid, info);
+      } else {
+        struct capmgr_package_info_s found = search_info->second;
+        found.appid_list.emplace_back(appid);
+      }
+    }
+  }
+
+  for (auto it = pkg_map.begin(); it != pkg_map.end(); it++) {
+    struct capmgr_package_info_s info = it->second;
+    if (cb(&info, user_data))
+      break;
+  }
+
+  return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_package_info_foreach_applications(
+    const capmgr_package_info_h remote_pkg_info,
+    capmgr_package_info_foreach_app_cb cb,
+    void* user_data) {
+  if (!cb)
+    return CAPMGR_ERROR_INVALID_PARAMETER;
+
+  return CAPMGR_ERROR_NONE;
+}
index 09e29a8de521d70902db68a751361fb9221e381a..52d54b6561b38c9868bf50b68b8d8f6411785ee1 100644 (file)
@@ -29,12 +29,29 @@ typedef struct capmgr_device_s* capmgr_device_h;
  */
 typedef struct capmgr_app_control_s* capmgr_app_control_h;
 
+/**
+ * @brief
+ */
+typedef struct capmgr_package_info_s* capmgr_package_info_h;
+
 /**
  * @brief
  */
 typedef int (*capmgr_device_foreach_cb)(const capmgr_device_h device,
     void* user_data);
 
+/**
+ * @brief
+ */
+typedef int (*capmgr_package_info_foreach_package_cb)(
+    const capmgr_package_info_h remote_package_info, void* user_data);
+
+/**
+ * @brief
+ */
+typedef int (*capmgr_package_info_foreach_app_cb)(
+    const char* appid, void* user_data);
+
 /**
  * @brief
  */
@@ -192,6 +209,38 @@ int capmgr_app_control_remove_extra_data(capmgr_app_control_h app_control,
  */
 int capmgr_app_control_send(capmgr_app_control_h app_control);
 
+/**
+ * @brief
+ */
+int capmgr_package_info_foreach_packages(const capmgr_device_h device,
+    capmgr_package_info_foreach_package_cb cb, void* user_data);
+
+/**
+ * @brief
+ */
+int capmgr_package_info_foreach_applications(
+    const capmgr_package_info_h remote_package_info,
+    capmgr_package_info_foreach_app_cb cb, void* user_data);
+
+/**
+ * @brief
+ */
+int capmgr_package_info_get_pkgid(capmgr_package_info_h remote_package_info,
+    char** pkgid);
+
+/**
+ * @brief
+ */
+int capmgr_package_info_get_label(capmgr_package_info_h remote_package_info,
+    char** label);
+
+
+/**
+ * @brief
+ */
+int capmgr_package_info_get_version(capmgr_package_info_h remote_package_info,
+    char** version);
+
 #ifdef __cplusplus
 }
 #endif
index 4b1c8d5d79007d25bb8a079a834ad64d1751efe7..8dce347d1f9eb5e7f6aa7da9fcba1a4639650adf 100644 (file)
@@ -38,6 +38,16 @@ const char kQueryInitCapsTable[] =
     "  PRIMARY KEY (device_id, operation, uri, mime, appid),\n"
     "  FOREIGN KEY (device_id)\n"
     "  REFERENCES devices (device_id) ON DELETE CASCADE)";
+const char kQueryInitRemoteAppsTable[] =
+    "CREATE TABLE IF NOT EXISTS remote_app_info (\n"
+    "  device_id TEXT,\n"
+    "  appid     TEXT,\n"
+    "  pkgid     TEXT,\n"
+    "  label     TEXT,\n"
+    "  version     TEXT,\n"
+    "  PRIMARY KEY (device_id, appid),\n"
+    "  FOREIGN KEY (device_id)\n"
+    "  REFERENCES devices (device_id) ON DELETE CASCADE)";
 const char kQueryInsertDev[] =
     "INSERT INTO devices (device_id, address, model_name, device_name,"
     "  platform_ver, profile, sw_ver) "
@@ -50,7 +60,11 @@ const char kQueryInsertCap[] =
 const char kQueryDeleteCap[] =
     "DELETE FROM capabilities WHERE device_id=? AND operation=? AND uri=? AND "
     "  mime=? AND appid=?";
-
+const char kQueryInsertRemoteApp[] =
+    "INSERT INTO remote_app_info (device_id, appid, pkgid, label, version) "
+    "VALUES (?, ?, ?, ?, ?)";
+const char kQueryDeleteRemoteApp[] =
+    "DELETE FROM remote_app_info WHERE device_id=? AND pkgid=?";
 }  // namespace
 
 namespace capmgr {
@@ -205,6 +219,64 @@ bool DBManager::DeleteCapability(const std::string& device_id,
   return true;
 }
 
+bool DBManager::InsertRemotePackage(const std::string& device_id,
+    const RemotePackageInfo& remote_pkg_info) {
+  auto guard = Instance().sql_conn_->GetTransactionGuard();
+  std::shared_ptr<SQLStatement> stmt = Instance().sql_conn_->PrepareStatement(
+      kQueryInsertRemoteApp);
+
+  for (const auto& appid : remote_pkg_info.appids()) {
+    int idx = 1;
+    if (!stmt->BindString(idx++, device_id))
+      return false;
+    if (!stmt->BindString(idx++, appid))
+      return false;
+    if (!stmt->BindString(idx++, remote_pkg_info.pkgid()))
+      return false;
+    if (!stmt->BindString(idx++, remote_pkg_info.label()))
+      return false;
+    if (!stmt->BindString(idx++, remote_pkg_info.version()))
+      return false;
+
+    if (stmt->Step() != SQLStatement::StepResult::DONE) {
+      LOG(ERROR) << "Failed to insert remote_app_info into db";
+      return false;
+    }
+    if (!stmt->Reset()) {
+      LOG(ERROR) << "Failed to reset statement";
+      return false;
+    }
+    stmt->Clear();
+  }
+
+  return true;
+}
+
+bool DBManager::DeleteRemotePackage(const std::string& device_id,
+    const RemotePackageInfo& remote_pkg_info) {
+  auto guard = Instance().sql_conn_->GetTransactionGuard();
+  std::shared_ptr<SQLStatement> stmt = Instance().sql_conn_->PrepareStatement(
+      kQueryDeleteRemoteApp);
+  if (!stmt) {
+    LOG(ERROR) << "Failed to prepare statement";
+    return false;
+  }
+
+  int idx = 1;
+  if (!stmt->BindString(idx++, device_id))
+    return false;
+  if (!stmt->BindString(idx++, remote_pkg_info.pkgid()))
+    return false;
+
+  if (stmt->Step() != SQLStatement::StepResult::DONE) {
+    LOG(ERROR) << "Failed to delete remote_app_info from db";
+    return false;
+  }
+
+  return true;
+}
+
+
 DBManager& DBManager::Instance() {
   static DBManager instance(kDBPath);
   return instance;
@@ -241,6 +313,16 @@ bool DBManager::InitTable(const std::unique_ptr<SQLConnection>& conn) {
     return false;
   }
 
+  stmt = conn->PrepareStatement(kQueryInitRemoteAppsTable);
+  if (!stmt) {
+    LOG(ERROR) << "Failed to prepare statement";
+    return false;
+  }
+  if (stmt->Step() != SQLStatement::StepResult::DONE) {
+    LOG(ERROR) << "Failed to create remote_app_info table";
+    return false;
+  }
+
   return true;
 }
 
index ca521ba9f560768d1f051feda02c9999de7007a0..0e5308e09e0c2d7faf4221ba1c73f3330840fa59 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "common/capability.h"
 #include "common/remote_device.h"
+#include "common/remote_package_info.h"
 
 namespace capmgr {
 
@@ -27,6 +28,10 @@ class DBManager {
       const std::vector<Capability>& caps);
   static bool DeleteCapability(const std::string& device_id,
       const Capability& cap);
+  static bool InsertRemotePackage(const std::string& device_id,
+    const RemotePackageInfo& remote_pkg_info);
+  static bool DeleteRemotePackage(const std::string& device_id,
+    const RemotePackageInfo& remote_pkg_info);
 
  private:
   explicit DBManager(const std::string& path);
diff --git a/src/common/remote_package_info.h b/src/common/remote_package_info.h
new file mode 100644 (file)
index 0000000..cbf9b2b
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_REMOTE_PACKAGE_INFO_H_
+#define COMMON_REMOTE_PACKAGE_INFO_H_
+
+#include <json/json.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace capmgr {
+
+class RemotePackageInfo {
+ public:
+  explicit RemotePackageInfo(const std::string& pkgid, const std::string& label,
+    const std::string& version, const std::vector<std::string>& appids)
+      : pkgid_(std::move(pkgid)), label_(std::move(label)),
+        version_(std::move(version)), appids_(std::move(appids)) {}
+
+  explicit RemotePackageInfo(const std::string& json_string) {
+    Json::Reader reader;
+    Json::Value root;
+
+    if (reader.parse(json_string, root)) {
+      Json::Value appid_list;
+      appid_list = root["appids"];
+
+      for (Json::Value::const_iterator it = appid_list.begin();
+          it != appid_list.end(); it++) {
+        appids_.push_back(it.key().asString());
+      }
+
+      pkgid_ = root["pkgid"].asString();
+      label_ = root["label"].asString();
+      version_ = root["version"].asString();
+    }
+  }
+
+  std::string Serialize() const {
+    Json::Value root;
+    Json::Value appid_list;
+
+    for (auto it = appids_.cbegin(); it != appids_.cend(); it++) {
+      Json::Value appid;
+      appid["appid"] = *it;
+      appid_list.append(appid);
+    }
+    root["appids"] = appid_list;
+    root["pkgid"] = this->pkgid();
+    root["label"] = this->label();
+    root["version"] = this->version();
+    Json::FastWriter writer;
+    return writer.write(root);
+  }
+
+  const std::string& pkgid() const { return pkgid_; }
+  const std::string& label() const { return label_; }
+  const std::string& version() const { return version_; }
+  const std::vector<std::string>& appids() const { return appids_; }
+
+ private:
+  std::string pkgid_;
+  std::string label_;
+  std::string version_;
+  std::vector<std::string> appids_;
+};
+
+}  // namespace capmgr
+
+#endif  // COMMON_REMOTE_PACKAGE_INFO_H_
index 01f116af65ca6bc3e99077076d00b0effc381b06..0cd003b2dfd9df5d26fbd61d35dbfd3f63b4cb3d 100644 (file)
@@ -13,6 +13,7 @@
 #include "common/capability.h"
 #include "common/db_manager.h"
 #include "common/remote_device.h"
+#include "common/remote_package_info.h"
 #include "common/utils/logging.h"
 
 namespace bf = boost::filesystem;
@@ -141,6 +142,29 @@ TEST_F(SmokeTest, DeleteCapTest) {
   ASSERT_TRUE(DBManager::DeleteCapability("deletecapdev", cap));
 }
 
+TEST_F(SmokeTest, InsertPkgTest) {
+  RemoteDevice dev("insertpkgdev", "addr1234", "tm1", "TM1", "5.0", "mobile",
+      "5.0");
+  ASSERT_TRUE(DBManager::InsertDevice(dev));
+  std::vector<std::string> v;
+  v.emplace_back("hello1");
+  v.emplace_back("hello2");
+  RemotePackageInfo info("org.tizen.hello", "hello", "0.0.1", v);
+  ASSERT_TRUE(DBManager::InsertRemotePackage("insertpkgdev", info));
+}
+
+TEST_F(SmokeTest, DeletePkgTest) {
+  RemoteDevice dev("deletepkgdev", "addr1234", "tm1", "TM1", "5.0", "mobile",
+      "5.0");
+  ASSERT_TRUE(DBManager::InsertDevice(dev));
+  std::vector<std::string> v;
+  v.emplace_back("hello1");
+  v.emplace_back("hello2");
+  RemotePackageInfo info("org.tizen.hello", "hello", "0.0.1", v);
+  ASSERT_TRUE(DBManager::InsertRemotePackage("deletepkgdev", info));
+  ASSERT_TRUE(DBManager::DeleteRemotePackage("deletepkgdev", info));
+}
+
 }  // namespace capmgr
 
 int main(int argc, char* argv[]) {