Remove trivial unnecessary build dependency
[apps/core/preloaded/lockscreen.git] / src / events.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <notification.h>
18 #include <notification_list.h>
19 #include <notification_internal.h>
20 #include <app_control_internal.h>
21 #include <Ecore.h>
22
23 #include "log.h"
24 #include "lockscreen.h"
25 #include "events.h"
26 #include "minicontrollers.h"
27
28 static Eina_List *notifications;
29 static Eina_List *minicontrollers;
30 static int init_count;
31 int LOCKSCREEN_EVENT_EVENTS_CHANGED;
32 static Ecore_Event_Handler *handler;
33 static bool freeze_event;
34
35 struct lockscreen_event {
36         lockscreen_event_type_e type;
37         union {
38                 char *icon_path;
39                 char *minicontroller_name;
40         };
41         char *icon_sub_path;
42         char *title;
43         char *content;
44         bundle *service_handle;
45         time_t time;
46         char *package;
47         notification_h noti;
48 };
49
50 static bool _notification_accept(notification_h noti)
51 {
52         int app_list = 0;
53         int ret = notification_get_display_applist(noti, &app_list);
54         if (ret != NOTIFICATION_ERROR_NONE) {
55                 ERR("notification_get_display_applist failed: %s", get_error_message(ret));
56                 return false;
57         }
58         return app_list & NOTIFICATION_DISPLAY_APP_LOCK;
59 }
60
61 static void _lockscreen_event_destroy(lockscreen_event_t *event)
62 {
63         if (event->title) free(event->title);
64         if (event->content) free(event->content);
65         if (event->icon_path) free(event->icon_path);
66         if (event->icon_sub_path) free(event->icon_sub_path);
67         if (event->package) free(event->package);
68         if (event->service_handle) bundle_free(event->service_handle);
69         if (event->noti) notification_free(event->noti);
70
71         free(event);
72 }
73
74 static lockscreen_event_t *_lockscreen_event_minicontroller_create(const char *mini_name)
75 {
76         lockscreen_event_t *event = calloc(1, sizeof(lockscreen_event_t));
77         if (!event) return NULL;
78
79         event->type = LOCKSCREEN_EVENT_TYPE_MINICONTROLLER;
80         event->minicontroller_name = mini_name ? strdup(mini_name) : NULL;
81
82         return event;
83 }
84
85 static lockscreen_event_t *_lockscreen_event_notification_create(notification_h noti)
86 {
87         int ret;
88         char *val;
89         lockscreen_event_t *event = calloc(1, sizeof(lockscreen_event_t));
90         if (!event) return NULL;
91
92         event->type = LOCKSCREEN_EVENT_TYPE_NOTIFICATION;
93
94         ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &val);
95         if (ret != NOTIFICATION_ERROR_NONE) {
96                 ERR("notification_get_text failed: %s", get_error_message(ret));
97                 _lockscreen_event_destroy(event);
98                 return NULL;
99         }
100         if (val) event->title = strdup(val);
101
102         ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, &val);
103         if (ret != NOTIFICATION_ERROR_NONE) {
104                 ERR("notification_get_text failed: %s", get_error_message(ret));
105                 _lockscreen_event_destroy(event);
106                 return NULL;
107         }
108         if (val) event->content = strdup(val);
109
110         ret = notification_get_pkgname(noti, &val);
111         if (ret != NOTIFICATION_ERROR_NONE) {
112                 ERR("notification_get_pkgname failed: %s", get_error_message(ret));
113                 _lockscreen_event_destroy(event);
114                 return NULL;
115         }
116         if (val) event->package = strdup(val);
117
118         ret = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &val);
119         if (ret != NOTIFICATION_ERROR_NONE) {
120                 ERR("notification_get_image failed: %s", get_error_message(ret));
121                 _lockscreen_event_destroy(event);
122                 return NULL;
123         }
124         if (val) event->icon_path = strdup(val);
125
126         ret = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, &val);
127         if (ret != NOTIFICATION_ERROR_NONE) {
128                 ERR("notification_get_image failed: %s", get_error_message(ret));
129                 _lockscreen_event_destroy(event);
130                 return NULL;
131         }
132         if (val) event->icon_sub_path = strdup(val);
133
134         ret = notification_get_time(noti, &event->time);
135         if (ret != NOTIFICATION_ERROR_NONE) {
136                 ERR("notification_get_time failed: %s", get_error_message(ret));
137                 _lockscreen_event_destroy(event);
138                 return NULL;
139         }
140
141         ret = notification_get_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, &event->service_handle);
142         if (ret != NOTIFICATION_ERROR_NONE) {
143                 ERR("notification_get_execute_option failed: %s", get_error_message(ret));
144                 _lockscreen_event_destroy(event);
145                 return NULL;
146         }
147
148         if (event->service_handle) {
149                 event->service_handle = bundle_dup(event->service_handle);
150         }
151
152         ret = notification_clone(noti, &event->noti);
153         if (ret != NOTIFICATION_ERROR_NONE) {
154                 ERR("notification_clone failed: %s", get_error_message(ret));
155                 _lockscreen_event_destroy(event);
156                 return NULL;
157         }
158
159         DBG("Title: %s", event->title);
160         DBG("Content: %s", event->content);
161         DBG("Package: %s", event->package);
162         DBG("Icon: %s", event->icon_path);
163         DBG("SubIcon: %s", event->icon_sub_path);
164
165         return event;
166 }
167
168 static int _load_notifications()
169 {
170         notification_list_h noti_list;
171         notification_list_h noti_list_head = NULL;
172         notification_h noti = NULL;
173
174         int ret = notification_get_list(NOTIFICATION_TYPE_NOTI, -1, &noti_list_head);
175         if (ret != NOTIFICATION_ERROR_NONE) {
176                 ERR("notification_get_list failed: %s", get_error_message(ret));
177                 return 1;
178         }
179
180         noti_list = noti_list_head;
181         while (noti_list) {
182                 noti = notification_list_get_data(noti_list);
183                 if (_notification_accept(noti)) {
184                         lockscreen_event_t *me = _lockscreen_event_notification_create(noti);
185                         notifications = eina_list_append(notifications, me);
186                 }
187                 noti_list = notification_list_get_next(noti_list);
188         }
189
190         ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
191
192         notification_free_list(noti_list_head);
193         return 0;
194 }
195
196 static void _unload_notifications()
197 {
198         lockscreen_event_t *event;
199
200         if (!notifications)
201                 return;
202
203         EINA_LIST_FREE(notifications, event)
204                 _lockscreen_event_destroy(event);
205
206         notifications = NULL;
207         ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
208 }
209
210 static void _noti_changed_cb(void *data, notification_type_e type, notification_op *op_list, int num_op)
211 {
212         _unload_notifications();
213         _load_notifications();
214 }
215
216 static void _unload_minicontrollers(void)
217 {
218         lockscreen_event_t *event;
219         EINA_LIST_FREE(minicontrollers, event)
220                 _lockscreen_event_destroy(event);
221         minicontrollers = NULL;
222         ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
223 }
224
225 static void _load_minicontrollers(void)
226 {
227         Eina_List *mini = lockscreen_minicontrollers_list_get();
228         const char *name;
229         EINA_LIST_FREE(mini, name) {
230                 lockscreen_event_t *event = _lockscreen_event_minicontroller_create(name);
231                 minicontrollers = eina_list_append(minicontrollers, event);
232         }
233         ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
234 }
235
236 static Eina_Bool _lockscreen_events_minicontroller_changed(void *data, int event, void *event_info)
237 {
238         _unload_minicontrollers();
239         _load_minicontrollers();
240         return EINA_TRUE;
241 }
242
243 int lockscreen_events_init(void)
244 {
245         if (!init_count) {
246                 LOCKSCREEN_EVENT_EVENTS_CHANGED = ecore_event_type_new();
247                 if (lockscreen_minicontrollers_init()) {
248                         ERR("lockscreen_minicontrollers_init failed");
249                         return 1;
250                 }
251                 int ret = notification_register_detailed_changed_cb(_noti_changed_cb, NULL);
252                 if (ret != NOTIFICATION_ERROR_NONE) {
253                         ERR("notification_register_detailed_changed_cb failed: %d", get_error_message(ret));
254                         return 1;
255                 }
256                 handler = ecore_event_handler_add(LOCKSCREEN_EVENT_MINICONTROLLERS_CHANGED, _lockscreen_events_minicontroller_changed, NULL);
257                 if (_load_notifications()) {
258                         ERR("load_notifications failed");
259                         return 1;
260                 }
261         }
262         init_count++;
263         return 0;
264 }
265
266 void lockscreen_events_shutdown(void)
267 {
268         if (init_count) {
269                 init_count--;
270                 if (!init_count) {
271                         int ret = notification_unregister_detailed_changed_cb(_noti_changed_cb, NULL);
272                         if (ret != NOTIFICATION_ERROR_NONE) {
273                                 ERR("notification_unregister_detailed_changed_cb failed: %s", get_error_message(ret));
274                         }
275                         _unload_notifications();
276                         _unload_minicontrollers();
277                         ecore_event_handler_del(handler);
278                 }
279         }
280 }
281
282 static void _app_control_reply_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
283 {
284         bool ret = false;
285         Launch_Result_Cb cb = user_data;
286
287         switch (result) {
288                 case APP_CONTROL_RESULT_APP_STARTED:
289                 case APP_CONTROL_RESULT_SUCCEEDED:
290                         ret = true;
291                         break;
292                 case APP_CONTROL_RESULT_FAILED:
293                 case APP_CONTROL_RESULT_CANCELED:
294                         ret = false;
295                         break;
296         }
297         if (cb) cb(ret);
298 }
299
300 bool lockscreen_event_launch(lockscreen_event_t *event, Launch_Result_Cb cb)
301 {
302         app_control_h service = NULL;
303
304         if (event->type != LOCKSCREEN_EVENT_TYPE_NOTIFICATION)
305                 return false;
306
307         int ret = app_control_create(&service);
308         if (ret != APP_CONTROL_ERROR_NONE) {
309                 ERR("app_control_create failed: %s", get_error_message(ret));
310                 return false;
311         }
312
313         ret = app_control_import_from_bundle(service, event->service_handle);
314         if (ret != APP_CONTROL_ERROR_NONE) {
315                 ERR("app_control_import_from_bundle: %s", get_error_message(ret));
316                 app_control_destroy(service);
317                 return false;
318         }
319
320         INF("Launching event for package: %s", event->package);
321
322         ret = app_control_send_launch_request(service, _app_control_reply_cb, cb);
323         if (ret != APP_CONTROL_ERROR_NONE) {
324                 ERR("app_control_send_launch_request failed: %s", get_error_message(ret));
325                 app_control_destroy(service);
326                 return false;
327         }
328
329         app_control_destroy(service);
330
331         return true;
332 }
333
334 Eina_List *lockscreen_events_get(void)
335 {
336         return eina_list_merge(eina_list_clone(notifications), eina_list_clone(minicontrollers));;
337 }
338
339 bool lockscreen_events_exists(void)
340 {
341         return notifications || minicontrollers ? EINA_TRUE : EINA_FALSE;
342 }
343
344 const char *lockscreen_event_title_get(const lockscreen_event_t *event)
345 {
346         return event->title;
347 }
348
349 const char *lockscreen_event_content_get(const lockscreen_event_t *event)
350 {
351         return event->content;
352 }
353
354 time_t lockscreen_event_time_get(const lockscreen_event_t *event)
355 {
356         return event->time;
357 }
358
359 const char *lockscreen_event_icon_get(const lockscreen_event_t *event)
360 {
361         return event->icon_path;
362 }
363
364 const char *lockscreen_event_sub_icon_get(const lockscreen_event_t *event)
365 {
366         return event->icon_sub_path;
367 }
368
369 lockscreen_event_type_e lockscreen_event_type_get(const lockscreen_event_t *event)
370 {
371         return event->type;
372 }
373
374 Evas_Object *lockscreen_event_minicontroller_create(lockscreen_event_t *event, Evas_Object *parent)
375 {
376         if (event->type != LOCKSCREEN_EVENT_TYPE_MINICONTROLLER)
377                 return NULL;
378         return lockscreen_minicontrollers_minicontroller_create(event->minicontroller_name, parent);
379 }
380
381 static void _lockscreen_event_notification_delete(notification_h noti)
382 {
383         int ret = notification_delete(noti);
384         if (ret != NOTIFICATION_ERROR_NONE) {
385                 ERR("notification_delete failed: %s", get_error_message(ret));
386         }
387 }
388
389 static void _lockscreen_event_minicontroller_delete(const char *name)
390 {
391         lockscreen_minicontrollers_minicontroller_stop(name);
392 }
393
394 void lockscreen_event_remove(lockscreen_event_t *event)
395 {
396         switch (event->type) {
397                 case LOCKSCREEN_EVENT_TYPE_NOTIFICATION:
398                         _lockscreen_event_notification_delete(event->noti);
399                         notifications = eina_list_remove(notifications, event);
400                         break;
401                 case LOCKSCREEN_EVENT_TYPE_MINICONTROLLER:
402                         _lockscreen_event_minicontroller_delete(event->minicontroller_name);
403                         minicontrollers = eina_list_remove(minicontrollers, event);
404                         break;
405         }
406         _lockscreen_event_destroy(event);
407         if (!freeze_event)
408                 ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
409 }
410
411 void lockscreen_events_remove_all(void)
412 {
413         lockscreen_event_t *event;
414         freeze_event = true;
415
416         EINA_LIST_FREE(notifications, event) {
417                 lockscreen_event_remove(event);
418         }
419         EINA_LIST_FREE(minicontrollers, event) {
420                 lockscreen_event_remove(event);
421         }
422         notifications = minicontrollers = NULL;
423         freeze_event = false;
424         ecore_event_add(LOCKSCREEN_EVENT_EVENTS_CHANGED, NULL, NULL, NULL);
425 }