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