7446f736596d6a6d87409e45970fb656da5f48ac
[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 #include <systemd/sd-login.h>
12 #include <tzplatform_config.h>
13
14 #include <cassert>
15 #include <map>
16 #include <vector>
17
18 #include "common/utils/pkgmgr_query.h"
19
20 namespace {
21
22 namespace ci = common_installer;
23
24 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
25 const std::map<ci::RequestType, const char*> kEventStr = {
26   {ci::RequestType::Install, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
27   {ci::RequestType::Recovery, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
28   {ci::RequestType::RecoveryUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
29   {ci::RequestType::Reinstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
30   {ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
31   {ci::RequestType::PartialUninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
32   {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
33   {ci::RequestType::ReadonlyUpdateInstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
34   {ci::RequestType::ReadonlyUpdateUninstall,
35       PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
36   {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
37   {ci::RequestType::Move, PKGMGR_INSTALLER_MOVE_EVENT_STR},
38   {ci::RequestType::MountInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
39   {ci::RequestType::MountUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
40   {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
41   {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
42   {ci::RequestType::ManifestPartialInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
43   {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
44   {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
45   {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
46   {ci::RequestType::MigrateExtImg, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
47   {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
48 };
49
50 }  // namespace
51
52 namespace common_installer {
53
54
55 PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi)
56     : pi_(pi), state_(State::NOT_SENT), request_type_(RequestType::Unknown),
57       error_message_sent_(false), is_upgrade_(false) {
58   uid_ = pkgmgr_installer_get_uid(pi_);
59   request_mode_ = GetRequestMode(uid_);
60 }
61
62 bool PkgmgrSignal::SendStarted(
63     const std::string& type, const std::string& pkgid) {
64   if (state_ != State::NOT_SENT)
65     return false;
66
67   if (!SetupUserList(pkgid))
68     LOG(WARNING) << "Failed to setup user list";
69
70   auto key = kEventStr.find(request_type_);
71   if (key == kEventStr.end())
72     return false;
73
74   if (strcmp(key->second, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
75     is_upgrade_ = true;
76
77   pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
78
79   if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid))
80     return false;
81
82   for (auto l : user_list_) {
83     key = kEventStr.find(l.second);
84     if (key == kEventStr.end())
85       continue;
86     SendSignal(l.first, PKGMGR_INSTALLER_START_KEY_STR, key->second, type,
87         pkgid);
88   }
89
90   state_ = State::STARTED;
91
92   // workaround for pkgmgr client to know all appids which are uninstalled
93   if (request_type_ == ci::RequestType::Uninstall) {
94     if (!SendAppids(type, pkgid))
95       return false;
96     for (auto l : user_list_)
97       SendAppids(l.first, type, pkgid);
98   }
99
100   return true;
101 }
102
103 bool PkgmgrSignal::SendProgress(int progress,
104     const std::string& type, const std::string& pkgid) {
105   if (state_ != State::STARTED)
106     return false;
107
108   if (!SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
109       std::to_string(progress).c_str(), type, pkgid))
110     return false;
111   for (auto l : user_list_) {
112     // ignore error case
113     SendSignal(l.first, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
114         std::to_string(progress).c_str(), type, pkgid);
115   }
116
117   return true;
118 }
119
120 bool PkgmgrSignal::SendFinished(
121     Step::Status result, const std::string& type, const std::string& pkgid) {
122   if (state_ != State::STARTED)
123     return false;
124
125   pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
126
127   if (result != Step::Status::OK && !error_message_sent_) {
128     if (!SendSignal(
129         PKGMGR_INSTALLER_ERROR_KEY_STR,
130         std::to_string(static_cast<int>(result)).c_str(), type, pkgid))
131       return false;
132
133     for (auto l : user_list_)
134       SendSignal(l.first,
135           PKGMGR_INSTALLER_ERROR_KEY_STR,
136           std::to_string(static_cast<int>(result)).c_str(), type, pkgid);
137   }
138   if (!SendSignal(
139       PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid))
140     return false;
141
142   for (auto l : user_list_)
143     SendSignal(l.first,
144         PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid);
145   state_ = State::FINISHED;
146   return true;
147 }
148
149 bool PkgmgrSignal::SendError(
150     Step::Status result,
151     const std::string& error_message,
152     const std::string& type,
153     const std::string& pkgid) {
154   if (state_ != State::STARTED)
155     return false;
156
157   pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
158
159   std::string error_value = std::to_string(static_cast<int>(result));
160   if (!error_message.empty())
161     error_value = error_value + ":" + error_message;
162
163   LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
164   error_message_sent_ = true;
165   if (!SendSignal(
166       PKGMGR_INSTALLER_ERROR_KEY_STR,
167       error_value.c_str(),
168       type,
169       pkgid))
170     return false;
171   for (auto l : user_list_)
172     SendSignal(l.first,
173         PKGMGR_INSTALLER_ERROR_KEY_STR,
174         error_value.c_str(),
175         type,
176         pkgid);
177   return true;
178 }
179
180 void PkgmgrSignal::SetRequestType(RequestType req_type) {
181   request_type_ = req_type;
182 }
183
184 bool PkgmgrSignal::SendSignal(
185     const char* key,
186     const char* value,
187     const std::string& type,
188     const std::string& pkgid) const {
189   // send pkgmgr signal
190   if (pkgmgr_installer_send_signal(
191         pi_,
192         !type.empty() ?  type.c_str(): "",
193         !pkgid.empty() ? pkgid.c_str() : "",
194         key,
195         value)) {
196     LOG(ERROR) << "Fail to send pkgmgr signal";
197     return false;
198   }
199
200   LOG(DEBUG) << "Success to send pkgmgr signal"
201              << " PKGID=" << pkgid
202              << " KEY=" << key
203              << " VALUE=" << value;
204   return true;
205 }
206
207 bool PkgmgrSignal::SendSignal(
208     uid_t uid,
209     const char* key,
210     const char* value,
211     const std::string& type,
212     const std::string& pkgid) const {
213   // send pkgmgr signal
214   if (pkgmgr_installer_send_signal_for_uid(
215         pi_,
216         uid,
217         !type.empty() ?  type.c_str(): "",
218         !pkgid.empty() ? pkgid.c_str() : "",
219         key,
220         value)) {
221     LOG(ERROR) << "Fail to send pkgmgr signal";
222     return false;
223   }
224
225   LOG(DEBUG) << "Success to send pkgmgr signal"
226              << " USER=" << uid
227              << " PKGID=" << pkgid
228              << " KEY=" << key
229              << " VALUE=" << value;
230   return true;
231 }
232
233 const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
234   switch (result) {
235     case Step::Status::OK:
236       return PKGMGR_INSTALLER_OK_EVENT_STR;
237     default:
238       return PKGMGR_INSTALLER_FAIL_EVENT_STR;
239   }
240 }
241
242 bool PkgmgrSignal::SendAppids(const std::string& type,
243                               const std::string& pkgid) const {
244   std::vector<std::string> appids;
245   ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
246   if (!pkg_query.AppidsForPkgId(&appids))
247     return true;
248   for (auto& appid : appids) {
249     if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
250                                                     pkgid.c_str(),
251                                                     appid.c_str()))
252       return false;
253   }
254   return true;
255 }
256
257 bool PkgmgrSignal::SendAppids(uid_t uid,
258                               const std::string& type,
259                               const std::string& pkgid) const {
260   std::vector<std::string> appids;
261   ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
262   if (!pkg_query.AppidsForPkgId(&appids))
263     return true;
264   for (auto& appid : appids) {
265     if (pkgmgr_installer_send_app_uninstall_signal_for_uid(
266         pi_, uid, type.c_str(), pkgid.c_str(), appid.c_str()))
267       return false;
268   }
269   return true;
270 }
271
272 bool PkgmgrSignal::SetupUserList(const std::string& pkgid) {
273   uid_t* uids = nullptr;
274   int n = sd_get_uids(&uids);
275
276   if (n < 0)
277     return false;
278   ci::PkgQueryInterface pkg_query_for_global(pkgid, kGlobalUserUid);
279   for (int i = 0; i < n; i++) {
280     ci::PkgQueryInterface pkg_query(pkgid, uids[i]);
281     switch (request_mode_) {
282       case RequestMode::GLOBAL:
283         // if user pkg is installed, installer will not send signal to user.
284         if (pkg_query.IsPackageInstalled(ci::RequestMode::USER))
285           continue;
286         else
287           user_list_.emplace_back(uids[i], request_type_);
288         break;
289       case RequestMode::USER:
290         if (uid_ != uids[i])
291           continue;
292         user_list_.emplace_back(uids[i], request_type_);
293         break;
294       default:
295         user_list_.emplace_back(uids[i], request_type_);
296         break;
297     }
298   }
299
300   if (uids)
301     free(uids);
302
303   return true;
304 }
305
306 }  // namespace common_installer