9119bc9962a4f9fa319d21c3247c25c00f415630
[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/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 PkgmgrSignal::State PkgmgrSignal::state_ = PkgmgrSignal::State::NOT_SENT;
55
56 PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi)
57     : pi_(pi), request_type_(RequestType::Unknown), error_message_sent_(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 (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid))
75     return false;
76
77   for (auto l : user_list_) {
78     key = kEventStr.find(l.second);
79     if (key == kEventStr.end())
80       continue;
81     SendSignal(l.first, PKGMGR_INSTALLER_START_KEY_STR, key->second, type,
82         pkgid);
83   }
84
85   state_ = State::STARTED;
86
87   // workaround for pkgmgr client to know all appids which are uninstalled
88   if (request_type_ == ci::RequestType::Uninstall) {
89     if (!SendAppids(type, pkgid))
90       return false;
91     for (auto l : user_list_)
92       SendAppids(l.first, type, pkgid);
93   }
94
95   return true;
96 }
97
98 bool PkgmgrSignal::SendProgress(int progress,
99     const std::string& type, const std::string& pkgid) {
100   if (state_ != State::STARTED)
101     return false;
102
103   if (!SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
104       std::to_string(progress).c_str(), type, pkgid))
105     return false;
106   for (auto l : user_list_) {
107     // ignore error case
108     SendSignal(l.first, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
109         std::to_string(progress).c_str(), type, pkgid);
110   }
111
112   return true;
113 }
114
115 bool PkgmgrSignal::SendFinished(
116     Step::Status result, const std::string& type, const std::string& pkgid) {
117   if (state_ != State::STARTED)
118     return false;
119
120   if (result != Step::Status::OK && !error_message_sent_) {
121     if (!SendSignal(
122         PKGMGR_INSTALLER_ERROR_KEY_STR,
123         std::to_string(static_cast<int>(result)).c_str(), type, pkgid))
124       return false;
125
126     for (auto l : user_list_)
127       SendSignal(l.first,
128           PKGMGR_INSTALLER_ERROR_KEY_STR,
129           std::to_string(static_cast<int>(result)).c_str(), type, pkgid);
130   }
131   if (!SendSignal(
132       PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid))
133     return false;
134
135   for (auto l : user_list_)
136     SendSignal(l.first,
137         PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid);
138   state_ = State::FINISHED;
139   return true;
140 }
141
142 bool PkgmgrSignal::SendError(
143     Step::Status result,
144     const std::string& error_message,
145     const std::string& type,
146     const std::string& pkgid) {
147   if (state_ != State::STARTED)
148     return false;
149
150   std::string error_value = std::to_string(static_cast<int>(result));
151   if (!error_message.empty())
152     error_value = error_value + ":" + error_message;
153
154   LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
155   error_message_sent_ = true;
156   if (!SendSignal(
157       PKGMGR_INSTALLER_ERROR_KEY_STR,
158       error_value.c_str(),
159       type,
160       pkgid))
161     return false;
162   for (auto l : user_list_)
163     SendSignal(l.first,
164         PKGMGR_INSTALLER_ERROR_KEY_STR,
165         error_value.c_str(),
166         type,
167         pkgid);
168   return true;
169 }
170
171 void PkgmgrSignal::SetRequestType(RequestType req_type) {
172   request_type_ = req_type;
173 }
174
175 bool PkgmgrSignal::SendSignal(
176     const char* key,
177     const char* value,
178     const std::string& type,
179     const std::string& pkgid) const {
180   // send pkgmgr signal
181   if (pkgmgr_installer_send_signal(
182         pi_,
183         !type.empty() ?  type.c_str(): "",
184         !pkgid.empty() ? pkgid.c_str() : "",
185         key,
186         value)) {
187     LOG(ERROR) << "Fail to send pkgmgr signal";
188     return false;
189   }
190
191   LOG(DEBUG) << "Success to send pkgmgr signal"
192              << " PKGID=" << pkgid
193              << " KEY=" << key
194              << " VALUE=" << value;
195   return true;
196 }
197
198 bool PkgmgrSignal::SendSignal(
199     uid_t uid,
200     const char* key,
201     const char* value,
202     const std::string& type,
203     const std::string& pkgid) const {
204   // send pkgmgr signal
205   if (pkgmgr_installer_send_signal_for_uid(
206         pi_,
207         uid,
208         !type.empty() ?  type.c_str(): "",
209         !pkgid.empty() ? pkgid.c_str() : "",
210         key,
211         value)) {
212     LOG(ERROR) << "Fail to send pkgmgr signal";
213     return false;
214   }
215
216   LOG(DEBUG) << "Success to send pkgmgr signal"
217              << " USER=" << uid
218              << " PKGID=" << pkgid
219              << " KEY=" << key
220              << " VALUE=" << value;
221   return true;
222 }
223
224 const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
225   switch (result) {
226     case Step::Status::OK:
227       return PKGMGR_INSTALLER_OK_EVENT_STR;
228     default:
229       return PKGMGR_INSTALLER_FAIL_EVENT_STR;
230   }
231 }
232
233 bool PkgmgrSignal::SendAppids(const std::string& type,
234                               const std::string& pkgid) const {
235   std::vector<std::string> appids;
236   ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
237   if (!pkg_query.AppidsForPkgId(&appids))
238     return true;
239   for (auto& appid : appids) {
240     if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
241                                                     pkgid.c_str(),
242                                                     appid.c_str()))
243       return false;
244   }
245   return true;
246 }
247
248 bool PkgmgrSignal::SendAppids(uid_t uid,
249                               const std::string& type,
250                               const std::string& pkgid) const {
251   std::vector<std::string> appids;
252   ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
253   if (!pkg_query.AppidsForPkgId(&appids))
254     return true;
255   for (auto& appid : appids) {
256     if (pkgmgr_installer_send_app_uninstall_signal_for_uid(
257         pi_, uid, type.c_str(), pkgid.c_str(), appid.c_str()))
258       return false;
259   }
260   return true;
261 }
262
263 bool PkgmgrSignal::SetupUserList(const std::string& pkgid) {
264   uid_t* uids = nullptr;
265   int n = sd_get_uids(&uids);
266
267   if (n < 0)
268     return false;
269   ci::PkgQueryInterface pkg_query_for_global(pkgid, kGlobalUserUid);
270   for (int i = 0; i < n; i++) {
271     ci::PkgQueryInterface pkg_query(pkgid, uids[i]);
272     switch (request_mode_) {
273       case RequestMode::GLOBAL:
274         // if user pkg is installed, installer will not send signal to user.
275         if (pkg_query.IsPackageInstalled(ci::RequestMode::USER))
276           continue;
277         else
278           user_list_.emplace_back(uids[i], request_type_);
279         break;
280       case RequestMode::USER:
281         if (uid_ != uids[i])
282           continue;
283         // if global pkg is installed,
284         // user pkg operation will be handled as update.
285         if (pkg_query_for_global.IsPackageInstalled(ci::RequestMode::GLOBAL))
286           user_list_.emplace_back(uids[i], RequestType::Update);
287         else
288           user_list_.emplace_back(uids[i], request_type_);
289         break;
290       default:
291         user_list_.emplace_back(uids[i], request_type_);
292         break;
293     }
294   }
295
296   if (uids)
297     free(uids);
298
299   return true;
300 }
301
302 }  // namespace common_installer