add new errors and error_message handlings
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_signal.cc
1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/pkgmgr_signal.h"
6
7 #include <manifest_parser/utils/logging.h>
8
9 #include <unistd.h>
10 #include <sys/types.h>
11
12 #include <cassert>
13 #include <map>
14 #include <vector>
15
16 #include "common/pkgmgr_registration.h"
17
18 namespace {
19
20 namespace ci = common_installer;
21
22 const std::map<ci::RequestType, const char*> kEventStr = {
23   {ci::RequestType::Install, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
24   {ci::RequestType::Recovery, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
25   {ci::RequestType::Reinstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
26   {ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
27   {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
28   {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
29   {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
30   {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR}
31 };
32
33 }  // namespace
34
35 namespace common_installer {
36
37 PkgmgrSignal::State PkgmgrSignal::state_ = PkgmgrSignal::State::NOT_SENT;
38
39 PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi, RequestType req_type)
40     : pi_(pi), request_type_(req_type), error_message_sent_(false) {
41 }
42
43 bool PkgmgrSignal::SendStarted(
44     const std::string& type, const std::string& pkgid) {
45   if (state_ != State::NOT_SENT) {
46     return false;
47   }
48
49   auto key = kEventStr.find(request_type_);
50   if (key == kEventStr.end()) {
51     return false;
52   }
53   if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid)) {
54     return false;
55   }
56
57   state_ = State::STARTED;
58
59   // workaround for pkgmgr client to know all appids which are uninstalled
60   if (request_type_ == ci::RequestType::Uninstall)
61     if (!SendAppids(type, pkgid))
62       return false;
63
64   return true;
65 }
66
67 bool PkgmgrSignal::SendProgress(int progress,
68     const std::string& type, const std::string& pkgid) {
69   if (state_ != State::STARTED) {
70     return false;
71   }
72
73   return SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
74       std::to_string(progress).c_str(), type, pkgid);
75 }
76
77 bool PkgmgrSignal::SendFinished(
78     Step::Status result, const std::string& type, const std::string& pkgid) {
79   if (state_ != State::STARTED) {
80     return false;
81   }
82   if (result != Step::Status::OK && !error_message_sent_) {
83     if (!SendSignal(
84         PKGMGR_INSTALLER_ERROR_KEY_STR,
85         std::to_string(static_cast<int>(result)).c_str(), type, pkgid)) {
86       return false;
87     }
88   }
89   if (!SendSignal(
90       PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid)) {
91     return false;
92   }
93   state_ = State::FINISHED;
94   return true;
95 }
96
97 bool PkgmgrSignal::SendError(
98     Step::Status result,
99     const std::string& error_message,
100     const std::string& type,
101     const std::string& pkgid) {
102   if (state_ != State::STARTED) {
103     return false;
104   }
105   std::string error_value = std::to_string(static_cast<int>(result));
106   if (!error_message.empty()) {
107     error_value = error_value + ":" + error_message;
108   }
109   LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
110   error_message_sent_ = true;
111   return SendSignal(
112     PKGMGR_INSTALLER_ERROR_KEY_STR,
113     error_value.c_str(),
114     type,
115     pkgid);
116 }
117
118 bool PkgmgrSignal::SendSignal(
119     const char* key,
120     const char* value,
121     const std::string& type,
122     const std::string& pkgid) const {
123   // send pkgmgr signal
124   if (pkgmgr_installer_send_signal(
125         pi_,
126         !type.empty() ?  type.c_str(): "",
127         !pkgid.empty() ? pkgid.c_str() : "",
128         key,
129         value)) {
130     LOG(ERROR) << "Fail to send pkgmgr signal";
131     return false;
132   }
133
134   LOG(DEBUG) << "Success to send pkgmgr signal"
135              << " PKGID=" << pkgid
136              << " KEY=" << key
137              << " VALUE=" << value;
138   return true;
139 }
140
141 const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
142   switch (result) {
143     case Step::Status::OK:
144       return PKGMGR_INSTALLER_OK_EVENT_STR;
145     default:
146       return PKGMGR_INSTALLER_FAIL_EVENT_STR;
147   }
148 }
149
150 bool PkgmgrSignal::SendAppids(const std::string& type,
151                               const std::string& pkgid) const {
152   std::vector<std::string> appids;
153   if (!QueryAppidsForPkgId(pkgid, &appids, getuid()))
154     return true;
155   for (auto& appid : appids) {
156     if (!pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
157                                                     pkgid.c_str(),
158                                                     appid.c_str()))
159       return false;
160   }
161   return true;
162 }
163
164 }  // namespace common_installer