Fix static analysis issue
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_signal.cc
index b850f70..78d41aa 100644 (file)
 
 #include <manifest_parser/utils/logging.h>
 
+#include <aul.h>
+#include <bundle_cpp.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <systemd/sd-login.h>
+#include <tzplatform_config.h>
 
 #include <cassert>
 #include <map>
 #include <vector>
 
-#include "common/pkgmgr_registration.h"
+#include "common/utils/pkgmgr_query.h"
 
 namespace {
 
 namespace ci = common_installer;
 
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 const std::map<ci::RequestType, const char*> kEventStr = {
   {ci::RequestType::Install, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
-  {ci::RequestType::Recovery, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
-  {ci::RequestType::Reinstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::Recovery, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+  {ci::RequestType::RecoveryUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::Reinstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+  {ci::RequestType::PartialUninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
   {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::ReadonlyUpdateInstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::ReadonlyUpdateUninstall,
+      PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::Move, PKGMGR_INSTALLER_MOVE_EVENT_STR},
+  {ci::RequestType::MountInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::MountUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
-  {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR}
+  {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::ManifestPartialInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+  {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::MigrateExtImg, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
 };
 
 }  // namespace
 
 namespace common_installer {
 
-PkgmgrSignal::State PkgmgrSignal::state_ = PkgmgrSignal::State::NOT_SENT;
 
-PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi, RequestType req_type)
-    : pi_(pi), request_type_(req_type), error_message_sent_(false) {
+PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi)
+    : pi_(pi), state_(State::NOT_SENT), request_type_(RequestType::Unknown),
+      error_message_sent_(false), is_upgrade_(false) {
+  uid_ = pkgmgr_installer_get_uid(pi_);
+  request_mode_ = GetRequestMode(uid_);
 }
 
 bool PkgmgrSignal::SendStarted(
     const std::string& type, const std::string& pkgid) {
-  if (state_ != State::NOT_SENT) {
+  if (state_ != State::NOT_SENT)
     return false;
-  }
+
+  if (!SetupUserList(pkgid))
+    LOG(WARNING) << "Failed to setup user list";
 
   auto key = kEventStr.find(request_type_);
-  if (key == kEventStr.end()) {
+  if (key == kEventStr.end())
     return false;
-  }
-  if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid)) {
+
+  if (strcmp(key->second, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
+    is_upgrade_ = true;
+
+  pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
+  if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid))
     return false;
+
+  for (const auto& l : user_list_) {
+    key = kEventStr.find(l.second);
+    if (key == kEventStr.end())
+      continue;
+    SendSignal(l.first, PKGMGR_INSTALLER_START_KEY_STR, key->second, type,
+        pkgid);
   }
 
   state_ = State::STARTED;
 
   // workaround for pkgmgr client to know all appids which are uninstalled
-  if (request_type_ == ci::RequestType::Uninstall)
+  if (request_type_ == ci::RequestType::Uninstall) {
     if (!SendAppids(type, pkgid))
       return false;
+    for (const auto& l : user_list_)
+      SendAppids(l.first, type, pkgid);
+  }
 
   return true;
 }
 
 bool PkgmgrSignal::SendProgress(int progress,
     const std::string& type, const std::string& pkgid) {
-  if (state_ != State::STARTED) {
+  if (state_ != State::STARTED)
+    return false;
+
+  if (!SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
+      std::to_string(progress).c_str(), type, pkgid))
     return false;
+  for (const auto& l : user_list_) {
+    // ignore error case
+    SendSignal(l.first, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
+        std::to_string(progress).c_str(), type, pkgid);
   }
 
-  return SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
-      std::to_string(progress).c_str(), type, pkgid);
+  return true;
 }
 
 bool PkgmgrSignal::SendFinished(
     Step::Status result, const std::string& type, const std::string& pkgid) {
-  if (state_ != State::STARTED) {
+  if (state_ != State::STARTED)
     return false;
-  }
+
+  pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
   if (result != Step::Status::OK && !error_message_sent_) {
     if (!SendSignal(
         PKGMGR_INSTALLER_ERROR_KEY_STR,
-        std::to_string(static_cast<int>(result)).c_str(), type, pkgid)) {
+        std::to_string(static_cast<int>(result)).c_str(), type, pkgid))
       return false;
-    }
+
+    for (const auto& l : user_list_)
+      SendSignal(l.first,
+          PKGMGR_INSTALLER_ERROR_KEY_STR,
+          std::to_string(static_cast<int>(result)).c_str(), type, pkgid);
   }
+
   if (!SendSignal(
-      PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid)) {
+      PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid))
     return false;
-  }
+
+  for (const auto& l : user_list_)
+    SendSignal(l.first,
+        PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid);
+
   state_ = State::FINISHED;
   return true;
 }
@@ -99,20 +155,34 @@ bool PkgmgrSignal::SendError(
     const std::string& error_message,
     const std::string& type,
     const std::string& pkgid) {
-  if (state_ != State::STARTED) {
+  if (state_ != State::STARTED)
     return false;
-  }
+
+  pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
   std::string error_value = std::to_string(static_cast<int>(result));
-  if (!error_message.empty()) {
+  if (!error_message.empty())
     error_value = error_value + ":" + error_message;
-  }
+
   LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
   error_message_sent_ = true;
-  return SendSignal(
-    PKGMGR_INSTALLER_ERROR_KEY_STR,
-    error_value.c_str(),
-    type,
-    pkgid);
+  if (!SendSignal(
+      PKGMGR_INSTALLER_ERROR_KEY_STR,
+      error_value.c_str(),
+      type,
+      pkgid))
+    return false;
+  for (const auto& l : user_list_)
+    SendSignal(l.first,
+        PKGMGR_INSTALLER_ERROR_KEY_STR,
+        error_value.c_str(),
+        type,
+        pkgid);
+  return true;
+}
+
+void PkgmgrSignal::SetRequestType(RequestType req_type) {
+  request_type_ = req_type;
 }
 
 bool PkgmgrSignal::SendSignal(
@@ -120,6 +190,19 @@ bool PkgmgrSignal::SendSignal(
     const char* value,
     const std::string& type,
     const std::string& pkgid) const {
+  if (!strcmp(key, "start") || !strcmp(key, "error") || !strcmp(key, "end")) {
+    uid_t uid = pkgmgr_installer_get_uid(pi_);
+    tizen_base::Bundle b({
+        { AUL_K_PKGID, pkgid },
+        { AUL_K_PACKAGETYPE, type },
+        { AUL_K_PKG_EVENT_NAME, key },
+        { AUL_K_PKG_EVENT_RESULT, value }
+        });
+
+    if (aul_package_pre_event_send(uid, b.GetHandle()) != AUL_R_OK)
+      LOG(ERROR) << "aul_package_pre_event_send() is failed";
+  }
+
   // send pkgmgr signal
   if (pkgmgr_installer_send_signal(
         pi_,
@@ -138,6 +221,32 @@ bool PkgmgrSignal::SendSignal(
   return true;
 }
 
+bool PkgmgrSignal::SendSignal(
+    uid_t uid,
+    const char* key,
+    const char* value,
+    const std::string& type,
+    const std::string& pkgid) const {
+  // send pkgmgr signal
+  if (pkgmgr_installer_send_signal_for_uid(
+        pi_,
+        uid,
+        !type.empty() ?  type.c_str(): "",
+        !pkgid.empty() ? pkgid.c_str() : "",
+        key,
+        value)) {
+    LOG(ERROR) << "Fail to send pkgmgr signal";
+    return false;
+  }
+
+  LOG(DEBUG) << "Success to send pkgmgr signal"
+             << " USER=" << uid
+             << " PKGID=" << pkgid
+             << " KEY=" << key
+             << " VALUE=" << value;
+  return true;
+}
+
 const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
   switch (result) {
     case Step::Status::OK:
@@ -150,10 +259,11 @@ const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
 bool PkgmgrSignal::SendAppids(const std::string& type,
                               const std::string& pkgid) const {
   std::vector<std::string> appids;
-  if (!QueryAppidsForPkgId(pkgid, &appids, getuid()))
+  ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
+  if (!pkg_query.AppidsForPkgId(&appids))
     return true;
   for (auto& appid : appids) {
-    if (!pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
+    if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
                                                     pkgid.c_str(),
                                                     appid.c_str()))
       return false;
@@ -161,4 +271,53 @@ bool PkgmgrSignal::SendAppids(const std::string& type,
   return true;
 }
 
+bool PkgmgrSignal::SendAppids(uid_t uid,
+                              const std::string& type,
+                              const std::string& pkgid) const {
+  std::vector<std::string> appids;
+  ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
+  if (!pkg_query.AppidsForPkgId(&appids))
+    return true;
+  for (auto& appid : appids) {
+    if (pkgmgr_installer_send_app_uninstall_signal_for_uid(
+        pi_, uid, type.c_str(), pkgid.c_str(), appid.c_str()))
+      return false;
+  }
+  return true;
+}
+
+bool PkgmgrSignal::SetupUserList(const std::string& pkgid) {
+  uid_t* uids = nullptr;
+  int n = sd_get_uids(&uids);
+
+  if (n < 0)
+    return false;
+  ci::PkgQueryInterface pkg_query_for_global(pkgid, kGlobalUserUid);
+  for (int i = 0; i < n; i++) {
+    ci::PkgQueryInterface pkg_query(pkgid, uids[i]);
+    switch (request_mode_) {
+      case RequestMode::GLOBAL:
+        // if user pkg is installed, installer will not send signal to user.
+        if (pkg_query.IsPackageInstalled(ci::RequestMode::USER))
+          continue;
+        else
+          user_list_.emplace_back(uids[i], request_type_);
+        break;
+      case RequestMode::USER:
+        if (uid_ != uids[i])
+          continue;
+        user_list_.emplace_back(uids[i], request_type_);
+        break;
+      default:
+        user_list_.emplace_back(uids[i], request_type_);
+        break;
+    }
+  }
+
+  if (uids)
+    free(uids);
+
+  return true;
+}
+
 }  // namespace common_installer