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 */
63 TPKP::UI::Response result;
69 result(TPKP::UI::Response::ERROR) {}
74 SockRaii() : sock(-1) {}
75 SockRaii(int _sock) : sock(_sock) {}
84 ElmRaii(int argc, char **argv)
89 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
94 SLOGD("elm_shutdown()");
99 void answerAllowCb(void *data, Evas_Object * /* obj */, void * /* event_info */)
101 SLOGD("allow answer");
103 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
104 TPKP_E_INTERNAL, "data shouldn't be null on evas callbacks");
106 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
107 pdp->result = Response::ALLOW;
109 evas_object_del(pdp->win);
112 void answerDenyCb(void *data, Evas_Object * /* obj */, void * /* event_info */)
114 SLOGD("deny answer");
116 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
117 TPKP_E_INTERNAL, "data shouldn't be null on evas callbacks");
119 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
120 pdp->result = Response::DENY;
122 evas_object_del(pdp->win);
125 Eina_Bool timeoutCb(void *data)
127 TPKP_CHECK_THROW_EXCEPTION(data != nullptr,
128 TPKP_E_INTERNAL, "data shouldn't be null on timeout callback");
129 TpkpPopup *pdp = static_cast<TpkpPopup *>(data);
130 pdp->result = Response::DENY;
132 SLOGI("popup timeout[%d](ms) reached! Let's deny", pdp->timeout);
134 evas_object_del(pdp->win);
136 return ECORE_CALLBACK_CANCEL;
139 std::unique_ptr<char> getPopupContentString(TpkpPopup *pdp)
141 char *contentFormat = dgettext(PROJECT_NAME, "SID_CONTENT_PUBLIC_KEY_MISMATCHED");
142 char *content = nullptr;
144 if (asprintf(&content, contentFormat, pdp->hostname.c_str()) == -1)
145 TPKP_THROW_EXCEPTION(TPKP_E_INTERNAL, "Failed to alloc memory for popup text");
147 return std::unique_ptr<char>(content);
154 * --------------------------------
157 * | ---------------------------- |
159 * | |--------------------------| |
160 * | | content (description) | |
162 * | | ----------- ----------- | |
163 * | | | button1 | | button2 | | |
164 * | | ----------- ----------- | |
165 * | ---------------------------- |
167 * --------------------------------
169 void showPopup(TpkpPopup *pdp)
171 SLOGD("Start to make popup");
173 TPKP_CHECK_THROW_EXCEPTION(pdp != nullptr,
174 TPKP_E_INTERNAL, "pdp shouldn't be null");
177 Evas_Object *win = elm_win_add(nullptr, "tpkp popup", ELM_WIN_NOTIFICATION);
178 elm_win_autodel_set(win, EINA_TRUE);
179 elm_win_indicator_opacity_set(win, ELM_WIN_INDICATOR_TRANSLUCENT);
180 elm_win_borderless_set(win, EINA_TRUE);
181 elm_win_alpha_set(win, EINA_TRUE);
182 evas_object_show(win);
185 auto contentString = getPopupContentString(pdp);
186 Evas_Object *popup = elm_popup_add(win);
187 evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
188 elm_object_text_set(popup, contentString.get());
189 elm_object_part_text_set(popup, "title,text", dgettext(PROJECT_NAME, "SID_TITLE_PUBLIC_KEY_MISMATCHED"));
190 evas_object_show(popup);
192 /* create allow button */
193 Evas_Object *buttonAllow = elm_button_add(popup);
194 elm_object_style_set(buttonAllow, "bottom");
195 elm_object_text_set(buttonAllow, dgettext(PROJECT_NAME, "SID_BTN_ALLOW"));
196 elm_object_part_content_set(popup, "button1", buttonAllow);
197 evas_object_smart_callback_add(buttonAllow, "clicked", answerAllowCb, pdp);
198 evas_object_show(buttonAllow);
200 /* create deny button */
201 Evas_Object *buttonDeny = elm_button_add(popup);
202 elm_object_style_set(buttonDeny, "bottom");
203 elm_object_text_set(buttonDeny, dgettext(PROJECT_NAME, "SID_BTN_DENY"));
204 elm_object_part_content_set(popup, "button2", buttonDeny);
205 evas_object_smart_callback_add(buttonDeny, "clicked", answerDenyCb, pdp);
206 evas_object_show(buttonDeny);
208 if (pdp->timeout > 0) {
209 ecore_timer_add(pdp->timeout / 1000, timeoutCb, pdp);
214 SLOGD("elm_run start");
220 * - std::string hostname
222 void deserialize(TpkpPopup *pdp, BinaryStream &stream)
224 Deserialization::Deserialize(stream, pdp->hostname);
225 Deserialization::Deserialize(stream, pdp->timeout);
227 SLOGD("Params from popup_runner: hostname[%s] timeout[%d]",
228 pdp->hostname.c_str(), pdp->timeout);
233 * - TPKP::UI::Response response (int)
235 BinaryStream serialize(TpkpPopup *pdp)
238 Serialization::Serialize(stream, static_cast<int>(pdp->result));
243 int getSockFromSystemd(void)
245 int n = sd_listen_fds(0);
247 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
248 if (sd_is_socket_unix(fd, SOCK_STREAM, 1, TPKP_UI_SOCK_ADDR, 0) > 0) {
249 SLOGD("Get socket from systemd. fd[%d]", fd);
253 TPKP_THROW_EXCEPTION(TPKP_E_INTERNAL, "Failed to get sock from systemd.");
256 } // namespace anonymous
258 int main(int argc, char **argv)
260 SLOGI("tpkp popup backend server start!");
262 /* init/shutdown elm automatically */
263 ElmRaii elmRaii(argc, argv);
265 setlocale(LC_ALL, vconf_get_str(VCONFKEY_LANGSET));
268 struct sockaddr_un clientaddr;
269 int client_len = sizeof(clientaddr);
271 struct pollfd fds[1];
272 fds[0].fd = getSockFromSystemd();
273 fds[0].events = POLLIN;
275 SLOGD("server fd from systemd: %d", fds[0].fd);
278 /* non blocking poll */
279 int ret = poll(fds, 1, 0);
280 TPKP_CHECK_THROW_EXCEPTION(ret >= 0,
281 TPKP_E_INTERNAL, "poll() error. errno: " << errno);
284 SLOGD("tpkp-popup backend service timeout. Let's be deactivated");
288 /* ready to accept! */
290 memset(&clientaddr, 0, client_len);
292 int clientFd = accept(fds[0].fd, (struct sockaddr *)&clientaddr, (socklen_t *)&client_len);
293 TPKP_CHECK_THROW_EXCEPTION(clientFd >= 0, TPKP_E_INTERNAL, "Error in func accept()");
294 SLOGD("client accepted with fd: %d", clientFd);
296 SockRaii clientSock(clientFd);
299 TpkpPopup *pdp = &pd;
301 /* receive arguments */
302 BinaryStream stream = receiveStream(clientFd);
303 deserialize(pdp, stream);
305 /* get user response */
307 SLOGD("pdp->result : %d", static_cast<int>(pdp->result));
310 stream = serialize(pdp);
311 sendStream(clientFd, stream);
313 SLOGD("tpkp-popup done successfully!");
315 } catch (const TPKP::Exception &e) {
316 SLOGE("Exception[%d]: %s", e.code(), e.what());
317 } catch (const std::bad_alloc &e) {
318 SLOGE("bad_alloc std exception: %s", e.what());
319 } catch (const std::exception &e) {
320 SLOGE("std exception: %s", e.what());
322 SLOGE("Unhandled exception occured!");