2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author Janusz Kozerski (j.kozerski@samsung.com)
30 #include <Elementary.h>
32 #include <systemd/sd-daemon.h>
36 * TODO(k.tak): Separate TPKP::Exception related codes from tpkp_common
37 * not to include "tpkp_common.h" which have lot of dependencies
39 #include "tpkp_common.h"
40 #include "tpkp_logger.h"
41 #include "ui/popup_common.h"
46 #define LOG_TAG "TPKP_POPUP"
48 #define TPKP_UI_SOCK_ADDR "/tmp/.tpkp-ui-backend.sock"
50 using namespace TPKP::UI;
59 /* internal data fields */
65 Evas_Object *buttonAllow;
66 Evas_Object *buttonDeny;
69 TPKP::UI::Response result;
81 result(TPKP::UI::Response::ERROR) {}
86 SockRaii() : sock(-1) {}
87 SockRaii(int _sock) : sock(_sock) {}
96 ElmRaii(int argc, char **argv)
101 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
106 SLOGD("elm_shutdown()");
111 void answerAllowCb(void *data, Evas_Object * /* obj */, void * /* event_info */)
113 SLOGD("allow answer");
115 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
116 TPKP_E_INTERNAL, "data shouldn't be null on evas callbacks");
118 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
119 pdp->result = Response::ALLOW;
121 evas_object_del(pdp->win);
124 void answerDenyCb(void *data, Evas_Object * /* obj */, void * /* event_info */)
126 SLOGD("deny answer");
128 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
129 TPKP_E_INTERNAL, "data shouldn't be null on evas callbacks");
131 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
132 pdp->result = Response::DENY;
134 evas_object_del(pdp->win);
137 Eina_Bool timeoutCb(void *data)
139 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
140 TPKP_E_INTERNAL, "data shouldn't be null on timeout callback");
141 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
142 pdp->result = Response::DENY;
144 SLOGI("popup timeout[%d](ms) reached! Let's deny", pdp->timeout);
146 evas_object_del(pdp->win);
148 return ECORE_CALLBACK_CANCEL;
155 * --------------------------------
158 * | ---------------------------- |
159 * | | content (description) | |
162 * | | ----------- ----------- | |
163 * | | | button1 | | button2 | | |
164 * | | ----------- ----------- | |
166 * | ---------------------------- |
167 * --------------------------------
169 /* TODO(k.tak): UI layout refinement */
170 void showPopup(TpkpPopup *pdp)
172 SLOGD("Start to make popup");
174 TPKP_CHECK_THROW_EXCEPTION(pdp != nullptr,
175 TPKP_E_INTERNAL, "pdp shouldn't be null");
177 pdp->win = elm_win_add(nullptr, "tpkp popup", ELM_WIN_NOTIFICATION);
179 elm_win_autodel_set(pdp->win, EINA_TRUE);
180 elm_win_indicator_opacity_set(pdp->win, ELM_WIN_INDICATOR_TRANSLUCENT);
181 elm_win_alpha_set(pdp->win, true);
182 evas_object_show(pdp->win);
184 pdp->popup = elm_popup_add(pdp->win);
185 evas_object_show(pdp->popup);
187 pdp->box = elm_box_add(pdp->popup);
188 evas_object_size_hint_weight_set(pdp->box, EVAS_HINT_EXPAND, 0);
189 evas_object_size_hint_align_set(pdp->box, EVAS_HINT_FILL, 0.0);
190 evas_object_show(pdp->box);
192 pdp->title = elm_label_add(pdp->popup);
193 elm_object_style_set(pdp->title, "elm.text.title");
194 elm_object_text_set(pdp->title, dgettext(PROJECT_NAME, "SID_TITLE_PUBLIC_KEY_MISMATCHED"));
195 evas_object_show(pdp->title);
196 elm_box_pack_end(pdp->box, pdp->title);
198 pdp->content = elm_label_add(pdp->popup);
199 elm_object_style_set(pdp->content, "elm.swallow.content");
200 elm_label_line_wrap_set(pdp->content, ELM_WRAP_MIXED);
201 char *contentFormat = dgettext(PROJECT_NAME, "SID_CONTENT_PUBLIC_KEY_MISMATCHED");
202 char *content = nullptr;
203 if (asprintf(&content, contentFormat, pdp->hostname.c_str()) == -1) {
204 SLOGE("Failed to alloc memory for popup text. Just go for it.");
205 elm_object_text_set(pdp->content, contentFormat);
207 elm_object_text_set(pdp->content, content);
211 evas_object_size_hint_weight_set(pdp->content, EVAS_HINT_EXPAND, 0.0);
212 evas_object_size_hint_align_set(pdp->content, EVAS_HINT_FILL, EVAS_HINT_FILL);
213 evas_object_show(pdp->content);
214 elm_box_pack_end(pdp->box, pdp->content);
216 elm_object_part_content_set(pdp->popup, "default", pdp->box);
218 pdp->buttonAllow = elm_button_add(pdp->popup);
219 elm_object_style_set(pdp->buttonAllow, "elm.swallow.content.button1");
220 elm_object_text_set(pdp->buttonAllow, dgettext(PROJECT_NAME, "SID_BTN_ALLOW"));
221 elm_object_part_content_set(pdp->popup, "button1", pdp->buttonAllow);
222 evas_object_smart_callback_add(pdp->buttonAllow, "clicked", answerAllowCb, pdp);
223 evas_object_show(pdp->buttonAllow);
225 pdp->buttonDeny = elm_button_add(pdp->popup);
226 elm_object_style_set(pdp->buttonDeny, "elm.swallow.content.button2");
227 elm_object_text_set(pdp->buttonDeny, dgettext(PROJECT_NAME, "SID_BTN_DENY"));
228 elm_object_part_content_set(pdp->popup, "button2 ", pdp->buttonDeny);
229 evas_object_smart_callback_add(pdp->buttonDeny, "clicked", answerDenyCb, pdp);
230 evas_object_show(pdp->buttonDeny);
232 if (pdp->timeout > 0) {
233 ecore_timer_add(pdp->timeout / 1000, timeoutCb, pdp);
236 SLOGD("elm_run start");
242 * - std::string hostname
244 void deserialize(TpkpPopup *pdp, BinaryStream &stream)
246 Deserialization::Deserialize(stream, pdp->hostname);
247 Deserialization::Deserialize(stream, pdp->timeout);
249 SLOGD("Params from popup_runner: hostname[%s] timeout[%d]",
250 pdp->hostname.c_str(), pdp->timeout);
255 * - TPKP::UI::Response response (int)
257 BinaryStream serialize(TpkpPopup *pdp)
260 Serialization::Serialize(stream, static_cast<int>(pdp->result));
265 int getSockFromSystemd(void)
267 int n = sd_listen_fds(0);
269 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
270 if (sd_is_socket_unix(fd, SOCK_STREAM, 1, TPKP_UI_SOCK_ADDR, 0) > 0) {
271 SLOGD("Get socket from systemd. fd[%d]", fd);
275 TPKP_THROW_EXCEPTION(TPKP_E_INTERNAL, "Failed to get sock from systemd.");
278 } // namespace anonymous
280 int main(int argc, char **argv)
282 SLOGI("tpkp popup backend server start!");
284 /* init/shutdown elm automatically */
285 ElmRaii elmRaii(argc, argv);
287 setlocale(LC_ALL, vconf_get_str(VCONFKEY_LANGSET));
290 struct sockaddr_un clientaddr;
291 int client_len = sizeof(clientaddr);
293 struct pollfd fds[1];
294 fds[0].fd = getSockFromSystemd();
295 fds[0].events = POLLIN;
297 SLOGD("server fd from systemd: %d", fds[0].fd);
300 /* non blocking poll */
301 int ret = poll(fds, 1, 0);
302 TPKP_CHECK_THROW_EXCEPTION(ret >= 0,
303 TPKP_E_INTERNAL, "poll() error. errno: " << errno);
306 SLOGD("tpkp-popup backend service timeout. Let's be deactivated");
310 /* ready to accept! */
312 memset(&clientaddr, 0, client_len);
314 int clientFd = accept(fds[0].fd, (struct sockaddr *)&clientaddr, (socklen_t *)&client_len);
315 TPKP_CHECK_THROW_EXCEPTION(clientFd >= 0, TPKP_E_INTERNAL, "Error in func accept()");
316 SLOGD("client accepted with fd: %d", clientFd);
318 SockRaii clientSock(clientFd);
321 TpkpPopup *pdp = &pd;
323 /* receive arguments */
324 BinaryStream stream = receiveStream(clientFd);
325 deserialize(pdp, stream);
327 /* get user response */
329 SLOGD("pdp->result : %d", static_cast<int>(pdp->result));
332 stream = serialize(pdp);
333 sendStream(clientFd, stream);
335 SLOGD("tpkp-popup done successfully!");
337 } catch (const TPKP::Exception &e) {
338 SLOGE("Exception[%d]: %s", e.code(), e.what());
339 } catch (const std::bad_alloc &e) {
340 SLOGE("bad_alloc std exception: %s", e.what());
341 } catch (const std::exception &e) {
342 SLOGE("std exception: %s", e.what());
344 SLOGE("Unhandled exception occured!");