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