Fix updating certinfo
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_registration.cc
index 665027d..57d3554 100644 (file)
 #include <tzplatform_config.h>
 #include <unistd.h>
 
+#include <vector>
+#include <utility>
+
+#include "common/utils/glist_range.h"
+#include "common/utils/manifest_util.h"
+
 namespace bf = boost::filesystem;
 
+
 namespace {
 
-bool RegisterCertificate(
-    const common_installer::CertificateInfo& cert_info,
+using CertInfo = common_installer::CertificateInfo;
+
+const char kWidgetApp[] = "widgetapp";
+
+bool RegisterCertificate(pkgmgr_instcertinfo_h handle,
+const ValidationCore::CertificatePtr& certPtr, pkgmgr_instcert_type type) {
+    if (certPtr) {
+      if (pkgmgr_installer_set_cert_value(handle, type,
+          const_cast<char*>(certPtr->getBase64().c_str())) < 0) {
+        pkgmgr_installer_destroy_certinfo_set_handle(handle);
+        LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
+        return false;
+      }
+    }
+    return true;
+}
+
+typedef Property<ValidationCore::CertificatePtr> CertInfo::*PropertyOfCertInf;
+
+const std::vector<std::pair<PropertyOfCertInf, pkgmgr_instcert_type>>
+    kCertTypePairs = {
+  {&CertInfo::auth_cert, PM_SET_AUTHOR_SIGNER_CERT},
+  {&CertInfo::auth_im_cert, PM_SET_AUTHOR_INTERMEDIATE_CERT},
+  {&CertInfo::auth_root_cert, PM_SET_AUTHOR_ROOT_CERT},
+  {&CertInfo::dist_cert, PM_SET_DISTRIBUTOR_SIGNER_CERT},
+  {&CertInfo::dist_im_cert,
+      PM_SET_DISTRIBUTOR_INTERMEDIATE_CERT},
+  {&CertInfo::dist_root_cert, PM_SET_DISTRIBUTOR_ROOT_CERT},
+  {&CertInfo::dist2_cert, PM_SET_DISTRIBUTOR2_SIGNER_CERT},
+  {&CertInfo::dist2_im_cert,
+      PM_SET_DISTRIBUTOR2_INTERMEDIATE_CERT},
+  {&CertInfo::dist2_root_cert, PM_SET_DISTRIBUTOR2_ROOT_CERT}
+};
+
+bool RegisterCertificates(
+    const CertInfo& cert_info,
     const std::string& pkgid, uid_t uid) {
   pkgmgr_instcertinfo_h handle;
   if (pkgmgr_installer_create_certinfo_set_handle(&handle) < 0) {
     LOG(ERROR) << "Cannot create pkgmgr_instcertinfo_h";
     return false;
   }
-
-  const auto& author_cert = cert_info.author_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle, PM_SET_AUTHOR_SIGNER_CERT,
-      const_cast<char*>(author_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
+  for (const auto& pair : kCertTypePairs) {
+     auto cert = (cert_info.*(pair.first)).get();
+     auto type = pair.second;
+     if (!RegisterCertificate(handle, cert, type))
+       return false;
   }
-
-  const auto& author_im_cert = cert_info.author_intermediate_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle, PM_SET_AUTHOR_INTERMEDIATE_CERT,
-      const_cast<char*>(author_im_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
-  }
-
-  const auto& author_root_cert = cert_info.author_root_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle, PM_SET_AUTHOR_ROOT_CERT,
-      const_cast<char*>(author_root_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
-  }
-
-  const auto& dist_cert = cert_info.distributor_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle, PM_SET_DISTRIBUTOR_SIGNER_CERT,
-      const_cast<char*>(dist_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
-  }
-
-  const auto& dist_im_cert =
-      cert_info.distributor_intermediate_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle,
-      PM_SET_DISTRIBUTOR_INTERMEDIATE_CERT,
-      const_cast<char*>(dist_im_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
-  }
-
-  const auto& dist_root_cert = cert_info.distributor_root_certificate.get();
-  if (pkgmgr_installer_set_cert_value(handle, PM_SET_DISTRIBUTOR_ROOT_CERT,
-      const_cast<char*>(dist_root_cert->getBase64().c_str())) < 0) {
-    pkgmgr_installer_destroy_certinfo_set_handle(handle);
-    LOG(ERROR) << "pkgmgrInstallerSetCertValue fail";
-    return false;
-  }
-
   if (pkgmgr_installer_save_certinfo(pkgid.c_str(), handle, uid) < 0) {
     pkgmgr_installer_destroy_certinfo_set_handle(handle);
     LOG(ERROR) << "Failed to save certificate information";
@@ -83,128 +79,117 @@ bool RegisterCertificate(
   return true;
 }
 
-int PkgmgrForeachAppCallback(const pkgmgrinfo_appinfo_h handle,
-                              void *user_data) {
-  auto* data = static_cast<std::vector<std::string>*>(user_data);
-  char* app_id = nullptr;
-  if (pkgmgrinfo_appinfo_get_appid(handle, &app_id) != PMINFO_R_OK)
-    return PMINFO_R_ERROR;
-  data->emplace_back(app_id);
-  return PMINFO_R_OK;
-}
-
-int PkgmgrForeachPrivilegeCallback(const char* privilege_name,
-                                   void* user_data) {
-  auto* data = static_cast<std::vector<std::string>*>(user_data);
-  data->emplace_back(privilege_name);
-  return PMINFO_R_OK;
-}
-
-// "preload" : this package was installed at the binary creation.
-// "system" : this package is "preload" and is not removable.
-// "update" : this package is "preload" but is updated after first installation.
-// "removable" : this package can be removed.
-// "readonly" : this package exists in readonly location.
-bool AssignPackageTags(manifest_x* manifest,
-                       common_installer::RequestMode,
-                       bool is_update) {
-  if (!strcmp(manifest->preload, "true")) {
-    manifest->removable = strdup("false");
-    manifest->readonly = strdup("true");
-    manifest->system = strdup("true");
-    if (is_update)
-      manifest->update = strdup("true");
-    else
-      manifest->update = strdup("false");
-  } else {
-    manifest->removable = strdup("true");
-    manifest->readonly = strdup("false");
-    manifest->system = strdup("false");
-    manifest->update = strdup("false");
+void AdjustWidgetNodisplayAttr(manifest_x* manifest) {
+  for (auto& app : GListRange<application_x*>(manifest->application)) {
+    if (!strcmp(app->component_type, kWidgetApp)) {
+      free(app->nodisplay);
+      // The nodisplay attribute of widget application should be true,
+      // but nodisplay of widget-service framework uses this attribute
+      // as defined at manifest file. So we need to adjust this value
+      // just before register in pkgmgr db.
+      app->nodisplay = strdup("true");
+    }
   }
-  // external installation should alter this flag
-  manifest->installed_storage = strdup("installed_internal");
-
-  return true;
 }
 
-}  // anonymous namespace
+}  // namespace
 
 namespace common_installer {
 
 bool RegisterAppInPkgmgr(manifest_x* manifest,
-                         const bf::path& xml_path,
                          const std::string& pkgid,
                          const CertificateInfo& cert_info,
                          uid_t uid,
+                         Storage storage,
                          RequestMode request_mode,
                          const boost::filesystem::path& tep_path) {
   // Fill "non-xml" elements
   if (!tep_path.empty())
     manifest->tep_name = strdup(tep_path.c_str());
 
-  if (!AssignPackageTags(manifest, request_mode, false))
-    return false;
+  if (storage == Storage::EXTENDED) {
+    bf::path ext_path = bf::path(GetExtendedRootAppPath(uid)) / pkgid;
+    manifest->external_path = strdup(ext_path.c_str());
+  } else if (storage == Storage::EXTERNAL) {
+    App2ExtDynamicService service;
+    std::string image_path = service.GetExternalImagePath(pkgid.c_str(), uid);
+    if (!image_path.empty())
+      manifest->external_path = strdup(image_path.c_str());
+  }
+
+  AdjustWidgetNodisplayAttr(manifest);
 
   int ret = request_mode != RequestMode::GLOBAL ?
-      pkgmgr_parser_process_usr_manifest_x_for_installation(manifest,
-          xml_path.c_str(), uid) :
-      pkgmgr_parser_process_manifest_x_for_installation(manifest,
-          xml_path.c_str());
+      pkgmgr_parser_process_usr_manifest_x_for_installation(manifest, uid) :
+      pkgmgr_parser_process_manifest_x_for_installation(manifest);
   if (ret) {
     LOG(ERROR) << "Failed to insert manifest into pkgmgr, error code=" << ret;
     return false;
   }
 
-  if (!!cert_info.author_certificate.get()) {
-    if (!RegisterCertificate(cert_info, pkgid, uid)) {
-      LOG(ERROR) << "Failed to register author certificate";
-      return false;
-    }
+  if (!RegisterCertificates(cert_info, pkgid, uid)) {
+    LOG(ERROR) << "Failed to register author certificate";
+    return false;
   }
 
   return true;
 }
 
 bool UpgradeAppInPkgmgr(manifest_x* manifest,
-                        const bf::path& xml_path,
                         const std::string& pkgid,
                         const CertificateInfo& cert_info,
                         uid_t uid,
+                        Storage storage,
                         RequestMode request_mode) {
-  if (!AssignPackageTags(manifest, request_mode, true))
-    return false;
+  if (storage == Storage::EXTENDED) {
+    bf::path ext_path = bf::path(GetExtendedRootAppPath(uid)) / pkgid;
+    manifest->external_path = strdup(ext_path.c_str());
+  } else if (storage == Storage::EXTERNAL) {
+    App2ExtDynamicService service;
+    std::string image_path = service.GetExternalImagePath(pkgid.c_str(), uid);
+    if (!image_path.empty())
+      manifest->external_path = strdup(image_path.c_str());
+  }
+
+  AdjustWidgetNodisplayAttr(manifest);
 
   int ret = request_mode != RequestMode::GLOBAL ?
-       pkgmgr_parser_process_usr_manifest_x_for_upgrade(manifest,
-          xml_path.c_str(), uid) :
-       pkgmgr_parser_process_manifest_x_for_upgrade(manifest, xml_path.c_str());
+       pkgmgr_parser_process_usr_manifest_x_for_upgrade(manifest, uid) :
+       pkgmgr_parser_process_manifest_x_for_upgrade(manifest);
 
   if (ret != 0) {
     LOG(ERROR) << "Failed to update manifest in pkgmgr, error code=" << ret;
     return false;
   }
 
-  (void) pkgmgr_installer_delete_certinfo(pkgid.c_str());
-  if (!!cert_info.author_certificate.get()) {
-    if (!RegisterCertificate(cert_info, pkgid, uid)) {
-      return false;
-    }
-  }
+  // TODO(jeremy.jang): consider updating cert only when dist cert is changed.
+  // because the package from different author is not allowed to be installed,
+  // so auth cert cannot be changed when update.
+  if (!RegisterCertificates(cert_info, pkgid, uid))
+    return false;
 
   return true;
 }
 
+bool UnregisterAppInPkgmgrForPkgId(const std::string& pkgid, uid_t uid,
+                                   RequestMode request_mode) {
+  manifest_x* manifest = PkgmgrGenerateManifestInfoFromDB(pkgid, uid);
+  if (!manifest) {
+    LOG(ERROR) << "Failed to get manifest_x from DB";
+    return false;
+  }
+  bool res = UnregisterAppInPkgmgr(manifest, pkgid, uid, request_mode);
+  pkgmgr_parser_free_manifest_xml(manifest);
+  return res;
+}
+
 bool UnregisterAppInPkgmgr(manifest_x* manifest,
-                           const bf::path& xml_path,
                            const std::string& pkgid,
                            uid_t uid,
                            RequestMode request_mode) {
   int ret = request_mode != RequestMode::GLOBAL ?
-      pkgmgr_parser_process_usr_manifest_x_for_uninstallation(manifest,
-          xml_path.c_str(), uid) :
-      pkgmgr_parser_process_manifest_x_for_uninstallation(manifest,
-          xml_path.c_str());
+      pkgmgr_parser_process_usr_manifest_x_for_uninstallation(manifest, uid) :
+      pkgmgr_parser_process_manifest_x_for_uninstallation(manifest);
   if (ret) {
     LOG(ERROR) << "Failed to delete manifest from pkgmgr, error code=" << ret;
     return false;
@@ -216,132 +201,109 @@ bool UnregisterAppInPkgmgr(manifest_x* manifest,
   return true;
 }
 
-std::string QueryCertificateAuthorCertificate(const std::string& pkgid,
-                                              uid_t uid) {
-  pkgmgrinfo_certinfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_create_certinfo(&handle);
-  if (ret != PMINFO_R_OK) {
-    LOG(DEBUG) << "pkgmgrinfo_pkginfo_create_certinfo failed with error: "
-               << ret;
-    return {};
-  }
-  ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid.c_str(), handle, uid);
-  if (ret != PMINFO_R_OK) {
-    LOG(DEBUG) << "pkgmgrinfo_pkginfo_load_certinfo failed with error: " << ret;
-    pkgmgrinfo_pkginfo_destroy_certinfo(handle);
-    return {};
-  }
-  const char* author_cert = nullptr;
-  ret = pkgmgrinfo_pkginfo_get_cert_value(handle, PMINFO_AUTHOR_SIGNER_CERT,
-                                          &author_cert);
-  if (ret != PMINFO_R_OK) {
-    LOG(DEBUG) << "pkgmgrinfo_pkginfo_get_cert_value failed with error: "
-               << ret;
-    pkgmgrinfo_pkginfo_destroy_certinfo(handle);
-    return {};
-  }
-  std::string old_author_certificate;
-  if (author_cert)
-    old_author_certificate = author_cert;
-  pkgmgrinfo_pkginfo_destroy_certinfo(handle);
-  return old_author_certificate;
-}
+bool UpdateTepInfoInPkgmgr(const bf::path& tep_path, const std::string& pkgid,
+                        uid_t uid, RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+        pkgmgr_parser_usr_update_tep(
+            pkgid.c_str(), tep_path.string().c_str(), uid) :
+        pkgmgr_parser_update_tep(
+            pkgid.c_str(), tep_path.string().c_str());
 
-std::string QueryTepPath(const std::string& pkgid, uid_t uid) {
-  pkgmgrinfo_pkginfo_h package_info;
-  if (pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid.c_str(), uid, &package_info)
-      != PMINFO_R_OK)
-    return {};
-  char* tep_name = nullptr;
-  int ret = pkgmgrinfo_pkginfo_get_tep_name(package_info, &tep_name);
-  if (ret != PMINFO_R_OK) {
-    LOG(DEBUG) << "pkgmgrinfo_pkginfo_get_tep_name failed with error: "
-               << ret;
-    pkgmgrinfo_pkginfo_destroy_pkginfo(package_info);
-    return {};
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to upgrade tep info: " << pkgid;
+    return false;
   }
-  std::string tep_name_value;
-  if (tep_name)
-    tep_name_value = tep_name;
-  pkgmgrinfo_pkginfo_destroy_pkginfo(package_info);
-  return tep_name_value;
+
+  return true;
 }
 
-bool QueryAppidsForPkgId(const std::string& pkg_id,
-                         std::vector<std::string>* result, uid_t uid) {
-  pkgmgrinfo_pkginfo_h package_info;
-  if (pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), uid, &package_info)
-      != PMINFO_R_OK) {
+bool UpdateInstalledStorageInPkgmgr(Storage storage, const bf::path& ext_path,
+                                    const std::string& pkgid, uid_t uid) {
+  // FIXME: refactor this
+  INSTALL_LOCATION install_location;
+  const char* path;
+  if (storage == Storage::INTERNAL) {
+    install_location = INSTALL_INTERNAL;
+    path = "";
+  } else if (storage == Storage::EXTERNAL) {
+    install_location = INSTALL_EXTERNAL;
+    path = ext_path.string().c_str();
+  } else {
+    install_location = INSTALL_EXTENDED;
+    path = ext_path.string().c_str();
+  }
+  int ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(
+      pkgid.c_str(), install_location, path, uid);
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to update installed storage info: " << pkgid;
     return false;
   }
 
-  bool ret = pkgmgrinfo_appinfo_get_usr_list(package_info, PMINFO_ALL_APP,
-      &PkgmgrForeachAppCallback, result, uid) == PMINFO_R_OK;
-  pkgmgrinfo_pkginfo_destroy_pkginfo(package_info);
-  return ret;
+  return true;
 }
 
-bool QueryPrivilegesForPkgId(const std::string& pkg_id, uid_t uid,
-                             std::vector<std::string>* result) {
-  pkgmgrinfo_pkginfo_h package_info;
-  if (pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), uid, &package_info)
-      != PMINFO_R_OK) {
+bool DisablePkgInPkgmgr(const std::string& pkgid, uid_t uid,
+                        RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+        pkgmgr_parser_update_pkg_disable_info_in_usr_db(pkgid.c_str(), uid, 1) :
+        pkgmgr_parser_update_pkg_disable_info_in_db(pkgid.c_str(), 1);
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to disable pkg: " << pkgid;
     return false;
   }
 
-  bool ret = pkgmgrinfo_pkginfo_foreach_privilege(package_info,
-      &PkgmgrForeachPrivilegeCallback, result) == PMINFO_R_OK;
-  pkgmgrinfo_pkginfo_destroy_pkginfo(package_info);
-  return ret;
+  return true;
 }
 
-bool IsPackageInstalled(const std::string& pkg_id, RequestMode request_mode) {
-  pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), getuid(),
-                                               &handle);
-  if (ret != PMINFO_R_OK)
-    return false;
-  bool is_global = false;
-  if (pkgmgrinfo_pkginfo_is_for_all_users(handle, &is_global) != PMINFO_R_OK) {
-    LOG(ERROR) << "pkgmgrinfo_pkginfo_is_for_all_users failed";
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-    return false;
-  }
-  if (request_mode != RequestMode::GLOBAL && is_global) {
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+bool EnablePkgInPkgmgr(const std::string& pkgid, uid_t uid,
+    RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+        pkgmgr_parser_update_pkg_disable_info_in_usr_db(pkgid.c_str(), uid, 0) :
+        pkgmgr_parser_update_pkg_disable_info_in_db(pkgid.c_str(), 0);
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to enable pkg: " << pkgid;
     return false;
   }
 
-  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
   return true;
 }
 
-bool IsPackageInstalled(const std::string& pkg_id, uid_t uid) {
-  pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), uid, &handle);
-  if (ret != PMINFO_R_OK)
-    return false;
-
-  bool is_global = false;
-  if (pkgmgrinfo_pkginfo_is_for_all_users(handle, &is_global) != PMINFO_R_OK) {
-    LOG(ERROR) << "pkgmgrinfo_pkginfo_is_for_all_users failed";
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+bool RegisterPluginInfo(manifest_x* manifest,
+                        uid_t uid,
+                        RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+      pkgmgr_parser_register_pkg_plugin_info_in_usr_db(manifest, uid) :
+      pkgmgr_parser_register_pkg_plugin_info_in_db(manifest);
+  if (ret) {
+    LOG(ERROR) << "Failed to insert plugin info, error code=" << ret;
     return false;
   }
+  return true;
+}
 
-  if (uid == GLOBAL_USER && is_global) {
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-    return true;
+bool UpdatePluginInfo(manifest_x* manifest,
+                      uid_t uid, RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+      pkgmgr_parser_update_pkg_plugin_info_in_usr_db(manifest, uid) :
+      pkgmgr_parser_update_pkg_plugin_info_in_db(manifest);
+  if (ret) {
+    LOG(ERROR) << "Failed to insert update plugin info, error code=" << ret;
+    return false;
   }
+  return true;
+}
 
-  if (uid != GLOBAL_USER && is_global) {
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+bool UnregisterPluginInfo(const std::string& pkgid,
+                          uid_t uid,
+                          RequestMode request_mode) {
+  int ret = request_mode != RequestMode::GLOBAL ?
+      pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(pkgid.c_str(), uid) :
+      pkgmgr_parser_unregister_pkg_plugin_info_in_db(pkgid.c_str());
+  if (ret) {
+    LOG(ERROR) << "Failed to remove plugin info, error code=" << ret;
     return false;
   }
-
-  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
   return true;
 }
 
-
 }  // namespace common_installer