power key popup : add power key popup for tv
[platform/core/system/system-popup.git] / signal-sender / signal-sender.c
1 /*
2  * system-popup
3  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <dlog.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <errno.h>
23 #include <bundle_internal.h>
24 #include <aul.h>
25 #include <appcore-efl.h>
26 #include <Ecore.h>
27 #include <Elementary.h>
28 #include <syspopup_caller.h>
29 #include <dbus/dbus.h>
30 #include "macro.h"
31
32 #define DBUS_REPLY_TIMEOUT  (120 * 1000)
33 #define BUF_MAX 256
34
35 #define MMC_ENCRYPTION_UG  "setting-mmc-encryption-efl"
36 #define SECURITY_UG        "setting-security-efl"
37
38 enum ode_error_type {
39         NOT_ENOUGH_SPACE,
40         OPERATION_FAILED,
41         ODE_ERROR_MAX,
42 };
43
44 static bool (*is_storage_encryption_restricted)(void) = NULL;
45
46 void register_storage_encryption_restricted_function(bool (*func)(void))
47 {
48         if (func)
49                 is_storage_encryption_restricted = func;
50 }
51
52 static Eina_Bool exit_idler_cb(void *data)
53 {
54         elm_exit();
55         return ECORE_CALLBACK_CANCEL;
56 }
57
58 static void sender_terminate(void)
59 {
60         if (ecore_idler_add(exit_idler_cb, NULL))
61                 return;
62         exit_idler_cb(NULL);
63 }
64
65 static int append_variant(DBusMessageIter *iter, const char *sig, char *param[])
66 {
67         char *ch;
68         int i, int_type;
69
70         if (!sig || !param)
71                 return 0;
72
73         for (ch = (char*)sig, i = 0; *ch != '\0'; ++i, ++ch) {
74                 switch (*ch) {
75                 case 's':
76                         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &param[i]);
77                         break;
78                 case 'i':
79                         int_type = atoi(param[i]);
80                         dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &int_type);
81                         break;
82                 default:
83                         _E("ERROR: %s %c", sig, *ch);
84                         return -EINVAL;
85                 }
86         }
87         return 0;
88 }
89
90 DBusMessage *call_dbus_method(const char *dest, const char *path,
91                 const char *interface, const char *method,
92                 const char *sig, char *param[])
93 {
94         DBusConnection *conn;
95         DBusMessage *msg = NULL;
96         DBusMessageIter iter;
97         DBusMessage *ret;
98         DBusError err;
99         int r;
100
101         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
102         if (!conn) {
103                 ret = NULL;
104                 goto out;
105         }
106
107         msg = dbus_message_new_method_call(dest, path, interface, method);
108         if (!msg) {
109                 ret = NULL;
110                 goto out;
111         }
112
113         dbus_message_iter_init_append(msg, &iter);
114         r = append_variant(&iter, sig, param);
115         if (r < 0) {
116                 ret = NULL;
117                 goto out;
118         }
119
120         /*This function is for synchronous dbus method call */
121         dbus_error_init(&err);
122         ret = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err);
123         dbus_error_free(&err);
124
125 out:
126         dbus_message_unref(msg);
127
128         return ret;
129 }
130
131 int call_dbus_method_for_pairs(const char *dest, const char *path,
132                 const char *interface, const char *method,
133                 int size, char *param[])
134 {
135         DBusConnection *conn;
136         DBusMessage *msg = NULL;
137         DBusMessage *reply;
138         DBusMessageIter iter, aiter, piter;
139         DBusError err;
140         int ret, result, i;
141         char *key, *value;
142
143         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
144         if (!conn) {
145                 ret = 0;
146                 _E("dbus_bus_get error");
147                 return -EPERM;
148         }
149
150         msg = dbus_message_new_method_call(dest, path, interface, method);
151         if (!msg) {
152                 _E("dbus_message_new_method_call(%s:%s-%s)", path, interface, method);
153                 return -EBADMSG;
154         }
155
156         dbus_message_iter_init_append(msg, &iter);
157         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{ss}", &aiter);
158         for (i = 0 ; i < size ; i = i + 2) {
159                 key = param[i];
160                 value = param[i+1];
161                 _I("key(%s), value(%s)", key, value);
162                 dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &piter);
163                 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &key);
164                 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &value);
165                 dbus_message_iter_close_container(&aiter, &piter);
166         }
167
168         dbus_message_iter_close_container(&iter, &aiter);
169         dbus_error_init(&err);
170
171         reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err);
172         dbus_message_unref(msg);
173         if (!reply) {
174                 _E("dbus_connection_send error(%s:%s) %s %s:%s-%s", err.name, err.message, dest, path, interface, method);
175                 dbus_error_free(&err);
176                 return -ECOMM;
177         }
178
179         ret = dbus_message_get_args(reply, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
180         dbus_message_unref(reply);
181         if (!ret) {
182                 _E("no message : [%s:%s] %s %s:%s-%s", err.name, err.message, dest, path, interface, method);
183                 dbus_error_free(&err);
184                 return -ENOMSG;
185         }
186
187         return result;
188 }
189
190 int request_to_launch_by_dbus(char *bus, char *path, char *iface,
191                 char *method, char *ptype, char *param[])
192 {
193         DBusMessage *msg;
194         DBusError err;
195         int i, r, ret_val;
196
197         i = 0;
198         do {
199                 msg = call_dbus_method(bus, path, iface, method, ptype, param);
200                 if (msg)
201                         break;
202                 i++;
203         } while (i < RETRY_MAX);
204         if (!msg) {
205                 _E("fail to call dbus method");
206                 return -ECONNREFUSED;
207         }
208
209         dbus_error_init(&err);
210         r = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID);
211         if (!r) {
212                 _E("no message : [%s:%s]", err.name, err.message);
213                 ret_val = -EBADMSG;
214         }
215
216         dbus_message_unref(msg);
217         dbus_error_free(&err);
218
219         return ret_val;
220 }
221
222
223 int request_to_launch_by_dbus_for_pairs(char *bus, char *path, char *iface,
224                 char *method, int size, char *param[])
225 {
226         return (call_dbus_method_for_pairs(bus, path, iface, method, size, param));
227 }
228
229 static int send_recovery_popup_signal(void)
230 {
231         char *param[2];
232
233         param[0] = "_SYSPOPUP_CONTENT_";
234         param[1] = "recovery";
235
236         return request_to_launch_by_dbus(BUS_NAME, POPUP_PATH_SYSTEM, POPUP_IFACE_SYSTEM,
237                         "RecoveryPopupLaunch", "ss", param);
238 }
239
240 static int send_usbstorage_unmount_popup_signal(char *path)
241 {
242         char *param[4];
243         char buf[BUF_MAX];
244
245         if (!path)
246                 return -EINVAL;
247
248         snprintf(buf, sizeof(buf), "%s", path);
249
250         param[0] = "_SYSPOPUP_CONTENT_";
251         param[1] = "usbotg_unmount_storage";
252         param[2] = "_DEVICE_PATH_";
253         param[3] = buf;
254
255         return request_to_launch_by_dbus_for_pairs(BUS_NAME, POPUP_PATH_SYSTEM, POPUP_IFACE_SYSTEM,
256                         "PopupLaunch", sizeof(param)/sizeof(param[0]), param);
257 }
258
259 static int send_cooldown_popup_signal(void)
260 {
261         char *param[2];
262
263         param[0] = "_SYSPOPUP_CONTENT_";
264         param[1] = "cooldown";
265
266         return request_to_launch_by_dbus_for_pairs(BUS_NAME, POPUP_PATH_SYSTEM, POPUP_IFACE_SYSTEM,
267                         "PopupLaunch", sizeof(param)/sizeof(param[0]), param);
268 }
269
270 static int get_err_and_space(bundle *b, char *type,
271                 char *error, int error_len, char *space, int space_len)
272 {
273         char *cErr, *spc;
274         int iErr;
275
276         cErr = (char *)bundle_get_val(b, SIGNAL_SENDER_ERROR_TYPE);
277         if (!cErr) {
278                 _E("Failed to get error type");
279                 return -ENOMEM;
280         }
281
282         spc = (char *)bundle_get_val(b, SIGNAL_SENDER_MEMORY_SPACE);
283         if (!spc) {
284                 _E("Failed to get memory space");
285                 return -ENOMEM;
286         }
287
288         iErr = atoi(cErr);
289         switch (iErr) {
290         case NOT_ENOUGH_SPACE:
291                 snprintf(error, error_len, "%s_not_enough_space", type);
292                 break;
293         case OPERATION_FAILED:
294                 snprintf(error, error_len, "%s_operation_failed", type);
295                 break;
296         default:
297                 _E("Unknown type (%d)", iErr);
298                 return -EINVAL;
299         }
300
301         snprintf(space, space_len, "%s", spc);
302
303         return 0;
304 }
305
306 static int send_ode_error_popup_signal(bundle *b, char *type)
307 {
308         int ret;
309         char error[BUF_MAX];
310         char space[BUF_MAX];
311         char *param[6];
312
313         if (!b || !type)
314                 return -EINVAL;
315
316         ret = get_err_and_space(b, type,
317                         error, sizeof(error), space, sizeof(space));
318         if (ret < 0)
319                 return ret;
320
321         param[0] = "_SYSPOPUP_CONTENT_";
322         param[1] = "ode_error";
323         param[2] = SIGNAL_SENDER_ERROR_TYPE;
324         param[3] = error;
325         param[4] = SIGNAL_SENDER_MEMORY_SPACE;
326         param[5] = space;
327
328         return request_to_launch_by_dbus(BUS_NAME, POPUP_PATH_SYSTEM, POPUP_IFACE_SYSTEM,
329                         "PopupLaunchTriple", "ssssss", param);
330 }
331
332 static int load_ode_setting_ug(void)
333 {
334         char *setting_ug;
335         bundle *b;
336         int ret;
337         bool restricted = false;
338
339         if (is_storage_encryption_restricted)
340                 restricted = is_storage_encryption_restricted();
341
342         if (restricted)
343                 setting_ug = SECURITY_UG;
344         else
345                 setting_ug = MMC_ENCRYPTION_UG;
346
347         b = bundle_create();
348         if (!b)
349                 return -ENOMEM;
350
351         ret = aul_launch_app(setting_ug, b);
352         bundle_free(b);
353         if (ret <= 0) {
354                 _E("Failed to launch app (%s)(%d)", setting_ug, ret);
355                 return ret;
356         }
357
358         return 0;
359 }
360
361 static int app_create(void *data)
362 {
363         return 0;
364 }
365
366 static int app_terminate(void *data)
367 {
368         return 0;
369 }
370
371 static int app_pause(void *data)
372 {
373         return 0;
374 }
375
376 static int app_resume(void *data)
377 {
378         return 0;
379 }
380
381 static int app_reset(bundle *b, void *data)
382 {
383         char *type;
384         char *path;
385         int ret;
386
387         if (!b) {
388                 ret = -EINVAL;
389                 goto out;
390         }
391
392         type = (char *)bundle_get_val(b, SIGNAL_SENDER_TYPE);
393         if (!type) {
394                 _E("FAIL: bundle_get_val()");
395                 ret = -ENOMEM;
396                 goto out;
397         }
398
399         if (!strncmp(type, SIGNAL_SENDER_TYPE_RECOVERY, strlen(SIGNAL_SENDER_TYPE_RECOVERY))) {
400                 ret = send_recovery_popup_signal();
401                 goto out;
402         }
403
404         if (!strncmp(type, SIGNAL_SENDER_TYPE_USBSTORAGE_UNMOUNT,
405                                 strlen(SIGNAL_SENDER_TYPE_USBSTORAGE_UNMOUNT))) {
406                 path = (char *)bundle_get_val(b, "_DEVICE_PATH_");
407                 if (!path) {
408                         _E("FAIL: bundle_get_val()");
409                         ret = -ENOMEM;
410                         goto out;
411                 }
412
413                 ret = send_usbstorage_unmount_popup_signal(path);
414                 goto out;
415         }
416
417         if (!strncmp(type, SIGNAL_SENDER_TYPE_COOLDOWN, strlen(SIGNAL_SENDER_TYPE_COOLDOWN))) {
418                 ret = send_cooldown_popup_signal();
419                 goto out;
420         }
421
422         if (!strncmp(type, SIGNAL_SENDER_TYPE_ENCRYPT, strlen(SIGNAL_SENDER_TYPE_ENCRYPT))) {
423                 ret = send_ode_error_popup_signal(b, type);
424                 goto out;
425         }
426
427         if (!strncmp(type, SIGNAL_SENDER_TYPE_DECRYPT, strlen(SIGNAL_SENDER_TYPE_DECRYPT))) {
428                 ret = send_ode_error_popup_signal(b, type);
429                 goto out;
430         }
431
432         if (!strncmp(type, SIGNAL_SENDER_TYPE_ODE_UG, strlen(type))) {
433                 ret = load_ode_setting_ug();
434                 goto out;
435         }
436
437         ret = -EINVAL;
438
439 out:
440         sender_terminate();
441         return ret;
442 }
443
444 int main(int argc, char *argv[])
445 {
446         struct appcore_ops ops = {
447                 .create = app_create,
448                 .terminate = app_terminate,
449                 .pause = app_pause,
450                 .resume = app_resume,
451                 .reset = app_reset,
452         };
453
454         return appcore_efl_main(PACKAGE, &argc, &argv, &ops);
455 }