Support legacy image for backward-compatibility
[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_INSTALL_EVENT_STR},
28   {ci::RequestType::Reinstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
29   {ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
30   {ci::RequestType::PartialUninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
31   {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
32   {ci::RequestType::ReadonlyUpdateInstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
33   {ci::RequestType::ReadonlyUpdateUninstall,
34       PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
35   {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
36   {ci::RequestType::Move, PKGMGR_INSTALLER_MOVE_EVENT_STR},
37   {ci::RequestType::MountInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
38   {ci::RequestType::MountUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
39   {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
40   {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
41   {ci::RequestType::ManifestPartialInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
42   {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
43   {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
44   {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
45   {ci::RequestType::MigrateExtImg, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
46   {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
47 };
48
49 }  // namespace
50
51 namespace common_installer {
52
53 PkgmgrSignal::State PkgmgrSignal::state_ = PkgmgrSignal::State::NOT_SENT;
54
55 PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi, RequestType req_type)
56     : pi_(pi), request_type_(req_type), error_message_sent_(false) {
57   uid_ = pkgmgr_installer_get_uid(pi_);
58   request_mode_ = GetRequestMode(uid_);
59 }
60
61 bool PkgmgrSignal::SendStarted(
62     const std::string& type, const std::string& pkgid) {
63   if (state_ != State::NOT_SENT) {
64     return false;
65   }
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   return true;
95 }
96
97 bool PkgmgrSignal::SendProgress(int progress,
98     const std::string& type, const std::string& pkgid) {
99   if (state_ != State::STARTED) {
100     return false;
101   }
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   return true;
112 }
113
114 bool PkgmgrSignal::SendFinished(
115     Step::Status result, const std::string& type, const std::string& pkgid) {
116   if (state_ != State::STARTED) {
117     return false;
118   }
119   if (result != Step::Status::OK && !error_message_sent_) {
120     if (!SendSignal(
121         PKGMGR_INSTALLER_ERROR_KEY_STR,
122         std::to_string(static_cast<int>(result)).c_str(), type, pkgid)) {
123       return false;
124     }
125     for (auto l : user_list_)
126       SendSignal(l.first,
127           PKGMGR_INSTALLER_ERROR_KEY_STR,
128           std::to_string(static_cast<int>(result)).c_str(), type, pkgid);
129   }
130   if (!SendSignal(
131       PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid)) {
132     return false;
133   }
134   for (auto l : user_list_)
135     SendSignal(l.first,
136         PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid);
137   state_ = State::FINISHED;
138   return true;
139 }
140
141 bool PkgmgrSignal::SendError(
142     Step::Status result,
143     const std::string& error_message,
144     const std::string& type,
145     const std::string& pkgid) {
146   if (state_ != State::STARTED) {
147     return false;
148   }
149   std::string error_value = std::to_string(static_cast<int>(result));
150   if (!error_message.empty()) {
151     error_value = error_value + ":" + error_message;
152   }
153   LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
154   error_message_sent_ = true;
155   if (!SendSignal(
156       PKGMGR_INSTALLER_ERROR_KEY_STR,
157       error_value.c_str(),
158       type,
159       pkgid))
160     return false;
161   for (auto l : user_list_)
162     SendSignal(l.first,
163         PKGMGR_INSTALLER_ERROR_KEY_STR,
164         error_value.c_str(),
165         type,
166         pkgid);
167   return true;
168 }
169
170 bool PkgmgrSignal::SendSignal(
171     const char* key,
172     const char* value,
173     const std::string& type,
174     const std::string& pkgid) const {
175   // send pkgmgr signal
176   if (pkgmgr_installer_send_signal(
177         pi_,
178         !type.empty() ?  type.c_str(): "",
179         !pkgid.empty() ? pkgid.c_str() : "",
180         key,
181         value)) {
182     LOG(ERROR) << "Fail to send pkgmgr signal";
183     return false;
184   }
185
186   LOG(DEBUG) << "Success to send pkgmgr signal"
187              << " PKGID=" << pkgid
188              << " KEY=" << key
189              << " VALUE=" << value;
190   return true;
191 }
192
193 bool PkgmgrSignal::SendSignal(
194     uid_t uid,
195     const char* key,
196     const char* value,
197     const std::string& type,
198     const std::string& pkgid) const {
199   // send pkgmgr signal
200   if (pkgmgr_installer_send_signal_for_uid(
201         pi_,
202         uid,
203         !type.empty() ?  type.c_str(): "",
204         !pkgid.empty() ? pkgid.c_str() : "",
205         key,
206         value)) {
207     LOG(ERROR) << "Fail to send pkgmgr signal";
208     return false;
209   }
210
211   LOG(DEBUG) << "Success to send pkgmgr signal"
212              << " USER=" << uid
213              << " PKGID=" << pkgid
214              << " KEY=" << key
215              << " VALUE=" << value;
216   return true;
217 }
218
219 const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
220   switch (result) {
221     case Step::Status::OK:
222       return PKGMGR_INSTALLER_OK_EVENT_STR;
223     default:
224       return PKGMGR_INSTALLER_FAIL_EVENT_STR;
225   }
226 }
227
228 bool PkgmgrSignal::SendAppids(const std::string& type,
229                               const std::string& pkgid) const {
230   std::vector<std::string> appids;
231   if (!QueryAppidsForPkgId(pkgid, &appids, pkgmgr_installer_get_uid(pi_)))
232     return true;
233   for (auto& appid : appids) {
234     if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
235                                                     pkgid.c_str(),
236                                                     appid.c_str()))
237       return false;
238   }
239   return true;
240 }
241
242 bool PkgmgrSignal::SendAppids(uid_t uid,
243                               const std::string& type,
244                               const std::string& pkgid) const {
245   std::vector<std::string> appids;
246   if (!QueryAppidsForPkgId(pkgid, &appids, pkgmgr_installer_get_uid(pi_)))
247     return true;
248   for (auto& appid : appids) {
249     if (pkgmgr_installer_send_app_uninstall_signal_for_uid(
250         pi_, uid, type.c_str(), pkgid.c_str(), appid.c_str()))
251       return false;
252   }
253   return true;
254 }
255
256 bool PkgmgrSignal::SetupUserList(const std::string& pkgid) {
257   int i;
258   uid_t* uids = nullptr;
259   int n = sd_get_uids(&uids);
260
261   if (n < 0)
262     return false;
263
264   for (i = 0; i < n; i++) {
265     switch (request_mode_) {
266       case RequestMode::GLOBAL:
267         // if user pkg is installed, installer will not send signal to user.
268         if (QueryIsPackageInstalled(pkgid, RequestMode::USER, uids[i]))
269           continue;
270         else
271           user_list_.emplace_back(uids[i], request_type_);
272         break;
273       case RequestMode::USER:
274         if (uid_ != uids[i])
275           continue;
276         // if global pkg is installed,
277         // user pkg operation will be handled as update.
278         if (QueryIsPackageInstalled(pkgid, kGlobalUserUid))
279           user_list_.emplace_back(uids[i], RequestType::Update);
280         else
281           user_list_.emplace_back(uids[i], request_type_);
282         break;
283       default:
284         user_list_.emplace_back(uids[i], request_type_);
285         break;
286     }
287   }
288
289   if (uids)
290     free(uids);
291
292   return true;
293 }
294
295 }  // namespace common_installer