f8b9cee00633d3b33df4266832e530b645135117
[platform/core/security/askuser.git] / src / agent / notification-daemon / GuiRunner.cpp
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /**
17  * @file        src/notification-daemon/GuiRunner.cpp
18  * @author      Oskar Ĺšwitalski <o.switalski@samsung.com>
19  * @brief       Definition of GuiRunner class
20  */
21
22 #include "GuiRunner.h"
23
24 #include <exception/ErrnoException.h>
25 #include <exception/Exception.h>
26 #include <translator/Translator.h>
27 #include <libintl.h>
28 #include <privilegemgr/privilege_info.h>
29
30 namespace AskUser {
31
32 namespace Notification {
33
34 namespace {
35
36 bool should_raise = false;
37
38 void unfocused(void *data, Evas_Object *, void *)
39 {
40     if (data == NULL)
41         return;
42
43     PopupData *res = static_cast<PopupData*>(data);
44
45     if (should_raise)
46         elm_win_raise(res->win);
47     else
48         elm_exit();
49 }
50
51 void inline win_close(Evas_Object *win) {
52     should_raise = false;
53     elm_win_lower(win);
54 }
55
56 void inline answer(void *data, NResponseType response)
57 {
58     ALOGD("User selected: " + Translator::Gui::responseToString(response));
59
60     if (data == NULL)
61         return;
62
63     PopupData *res = static_cast<PopupData*>(data);
64     res->type = response;
65     win_close(res->win);
66 }
67
68 void allow_answer(void *data, Evas_Object *, void *)
69 {
70     answer(data, NResponseType::Allow);
71 }
72
73 void deny_answer(void *data, Evas_Object *, void *)
74 {
75     answer(data, NResponseType::Deny);
76 }
77
78 void never_answer(void *data, Evas_Object *, void *)
79 {
80     answer(data, NResponseType::Never);
81 }
82
83 Eina_Bool timeout_answer(void *data) {
84     if (!data)
85         return ECORE_CALLBACK_RENEW;
86
87     drop *d = static_cast<drop*>(data);
88
89     if (d->handle()) {
90         win_close(d->popup->win);
91     }
92
93     return ECORE_CALLBACK_RENEW;
94 }
95
96 std::string friendlyPrivilegeName(const std::string &privilege)
97 {
98     char *privacy_display_name = nullptr;
99     int res = privilege_info_get_privilege_group_display_name(privilege.c_str(), &privacy_display_name);
100     if (res != PRVMGR_ERR_NONE || !privacy_display_name) {
101         ALOGE("Unable to get privilege group display name for: <" << privilege << ">, err: <" << res << ">");
102         return privilege;
103     }
104     std::unique_ptr<char, decltype(free)*> antiMemLeak(privacy_display_name, free);
105     std::string ret(privacy_display_name);
106     return ret;
107 }
108
109 } /* namespace */
110
111 GuiRunner::GuiRunner()
112 {
113     m_popupData = new PopupData({NResponseType::Deny, nullptr});
114 }
115
116 GuiRunner::~GuiRunner()
117 {
118     delete m_popupData;
119 }
120
121 void GuiRunner::initialize()
122 {
123     elm_init(0, NULL);
124
125     //placeholder
126     m_win = elm_win_add(NULL, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_TITLE"),
127                                    ELM_WIN_DOCK);
128     elm_win_autodel_set(m_win, EINA_TRUE);
129     elm_win_override_set(m_win, EINA_TRUE);
130     elm_win_alpha_set(m_win, EINA_TRUE);
131
132     // popup
133     m_popup = elm_popup_add(m_win);
134     elm_object_part_text_set(m_popup, "title,text", dgettext(PROJECT_NAME,
135                                                          "SID_PRIVILEGE_REQUEST_DIALOG_TITLE"));
136
137     // box
138     m_box = elm_box_add(m_popup);
139     evas_object_size_hint_weight_set(m_box, EVAS_HINT_EXPAND, 0);
140     evas_object_size_hint_align_set(m_box, EVAS_HINT_FILL, 0.0);
141
142     // content
143     m_content = elm_label_add(m_popup);
144     elm_object_style_set(m_content, "elm.swallow.content");
145     elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED);
146     evas_object_size_hint_weight_set(m_content, EVAS_HINT_EXPAND, 0.0);
147     evas_object_size_hint_align_set(m_content, EVAS_HINT_FILL, EVAS_HINT_FILL);
148
149     evas_object_show(m_content);
150     elm_box_pack_end(m_box, m_content);
151     elm_object_part_content_set(m_popup, "default", m_box);
152
153     // buttons
154     m_allowButton = elm_button_add(m_popup);
155     elm_object_part_content_set(m_popup, "button1", m_allowButton);
156     elm_object_text_set(m_allowButton, dgettext(PROJECT_NAME,
157                                             "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_ALLOW"));
158
159     m_neverButton = elm_button_add(m_popup);
160     elm_object_text_set(m_neverButton, dgettext(PROJECT_NAME,
161                                             "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_NEVER"));
162     elm_object_part_content_set(m_popup, "button2", m_neverButton);
163
164     m_denyButton = elm_button_add(m_popup);
165     elm_object_text_set(m_denyButton, dgettext(PROJECT_NAME,
166                                            "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_DENY"));
167     elm_object_part_content_set(m_popup, "button3", m_denyButton);
168
169     // callbacks
170     evas_object_smart_callback_add(m_win, "unfocused", unfocused, m_popupData);
171     evas_object_smart_callback_add(m_allowButton, "clicked", allow_answer, m_popupData);
172     evas_object_smart_callback_add(m_neverButton, "clicked", never_answer, m_popupData);
173     evas_object_smart_callback_add(m_denyButton, "clicked", deny_answer, m_popupData);
174
175     m_popupData->win = m_win;
176     m_initialized = true;
177
178 }
179
180 NResponseType GuiRunner::popupRun(const std::string &app, const std::string &perm)
181 {
182
183     try {
184         if (!m_dropHandler)
185             throw Exception("DropHandler was not initialized");
186
187         if (!m_initialized)
188             initialize();
189
190         m_running = true;
191         drop *Drop = new drop({m_dropHandler, m_popupData});
192         m_timer = ecore_timer_add(0.1, timeout_answer, Drop);
193
194         // create message
195         char *messageFormat = dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_MESSAGE");
196         char buf[BUFSIZ];
197         int ret = std::snprintf(buf, sizeof(buf), messageFormat,
198                                 app.c_str(),
199                                 friendlyPrivilegeName(perm).c_str());
200
201         if (ret < 0)
202             throw ErrnoException("snprintf failed", errno);
203
204         m_popupData->type = NResponseType::None;
205
206         should_raise = true;
207
208         elm_object_text_set(m_content, buf);
209
210         evas_object_show(m_popup);
211         evas_object_show(m_win);
212
213         elm_win_raise(m_win);
214         elm_run();
215
216         ecore_timer_del(m_timer);
217         m_running = false;
218         should_raise = false;
219     } catch (const std::exception &e) {
220         m_popupData->type = NResponseType::Error;
221         m_errorMsg = std::move(e.what());
222     }
223
224     return m_popupData->type;
225 }
226
227 void GuiRunner::setDropHandler(DropHandler dropHandler)
228 {
229     m_dropHandler = dropHandler;
230 }
231
232 void GuiRunner::stop()
233 {
234     if (m_running) {
235         evas_object_hide(m_win);
236         elm_exit();
237     }
238
239     elm_shutdown();
240 }
241
242 } /* namespace Notification */
243
244 } /* namespace AskUser */