Fix build error
[platform/core/appfw/data-provider-slave.git] / src / client.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 <stdio.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <malloc.h>
21
22 #include <Elementary.h>
23 #include <Eina.h>
24 #include <Ecore.h>
25
26 #include <app.h>
27 #include <dlog.h>
28 #include <aul.h>
29 #include <sqlite3.h>
30
31 #include <widget_errno.h> /* widget_service */
32 #include <widget_provider.h> /* widget_provider */
33 #include <widget_script.h> /* widget_service - widget_event_info */
34 #include <widget_conf.h>
35 #include <widget/widget_internal.h> /* widget - WIDGET_SYS_EVENT_XXX */
36 #include <widget/widget.h> /* widget - WIDGET_SYS_EVENT_XXX */
37
38 #include "critical_log.h"
39 #include "debug.h"
40 #include "client.h"
41 #include "so_handler.h"
42 #include "widget.h"
43 #include "util.h"
44 #include "conf.h"
45 #include "main.h"
46
47 struct pre_callback_item {
48         widget_pre_callback_t cb;
49         void *data;
50 };
51
52 static struct info {
53         Ecore_Timer *ping_timer;
54         Eina_List *widget_pre_callback_list[WIDGET_PRE_CALLBACK_COUNT];
55 } s_info = {
56         .ping_timer = NULL,
57         .widget_pre_callback_list = { NULL, },
58 };
59
60 static void invoke_pre_callback(widget_pre_callback_e type, const char *id)
61 {
62         Eina_List *l;
63         Eina_List *n;
64         struct pre_callback_item *item;
65
66         EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
67                 item->cb(id, item->data);
68         }
69 }
70
71 int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
72 {
73         struct pre_callback_item *item;
74         Eina_List *l;
75
76         if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
77                 return WIDGET_ERROR_INVALID_PARAMETER;
78         }
79
80         EINA_LIST_FOREACH(s_info.widget_pre_callback_list[type], l, item) {
81                 if (item->cb == cb && item->data == data) {
82                         return WIDGET_ERROR_ALREADY_EXIST;
83                 }
84         }
85
86         item = malloc(sizeof(*item));
87         if (!item) {
88                 ErrPrint("malloc: %d\n", errno);
89                 return WIDGET_ERROR_OUT_OF_MEMORY;
90         }
91
92         item->cb = cb;
93         item->data = data;
94
95         s_info.widget_pre_callback_list[type] = eina_list_append(s_info.widget_pre_callback_list[type], item);
96         return 0;
97 }
98
99 int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
100 {
101         Eina_List *l;
102         Eina_List *n;
103         struct pre_callback_item *item;
104
105         if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
106                 ErrPrint("Invalid parameter\n");
107                 return WIDGET_ERROR_INVALID_PARAMETER;
108         }
109
110         EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
111                 if (item->cb == cb && item->data == data) {
112                         s_info.widget_pre_callback_list[type] = eina_list_remove_list(s_info.widget_pre_callback_list[type], l);
113                         free(item);
114                         return WIDGET_ERROR_NONE;
115                 }
116         }
117
118         return WIDGET_ERROR_NOT_EXIST;
119 }
120
121 static int method_new(struct widget_event_arg *arg, int *width, int *height, double *priority, void *data)
122 {
123         int ret;
124         struct widget_create_arg _arg;
125         DbgPrint("Create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], skip[%d], abi[%s], size: %dx%d\n",
126                         arg->pkgname,
127                         arg->id,
128                         arg->info.widget_create.content,
129                         arg->info.widget_create.timeout,
130                         arg->info.widget_create.has_script,
131                         arg->info.widget_create.period,
132                         arg->info.widget_create.cluster, arg->info.widget_create.category,
133                         arg->info.widget_create.skip_need_to_create,
134                         arg->info.widget_create.abi,
135                         arg->info.widget_create.width,
136                         arg->info.widget_create.height);
137
138         if (!arg->info.widget_create.content || !strlen(arg->info.widget_create.content)) {
139                 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
140                 arg->info.widget_create.content = WIDGET_CONF_DEFAULT_CONTENT;
141         }
142
143         _arg.content = arg->info.widget_create.content;
144         _arg.timeout = arg->info.widget_create.timeout;
145         _arg.has_widget_script = arg->info.widget_create.has_script;
146         _arg.period = arg->info.widget_create.period;
147         _arg.cluster = arg->info.widget_create.cluster;
148         _arg.category = arg->info.widget_create.category;
149         _arg.abi = arg->info.widget_create.abi;
150         _arg.skip_need_to_create = arg->info.widget_create.skip_need_to_create;
151         _arg.direct_addr = arg->info.widget_create.direct_addr;
152
153         invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
154
155         ret = widget_create(arg->pkgname, arg->id,
156                         &_arg,
157                         width, height, priority,
158                         &arg->info.widget_create.out_content,
159                         &arg->info.widget_create.out_title);
160
161         if (ret == 0) {
162                 if (arg->info.widget_create.width > 0 && arg->info.widget_create.height > 0) {
163                         DbgPrint("Create size: %dx%d (created: %dx%d)\n", arg->info.widget_create.width, arg->info.widget_create.height, *width, *height);
164                         if (*width != arg->info.widget_create.width || *height != arg->info.widget_create.height) {
165                                 int tmp;
166                                 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_create.width, arg->info.widget_create.height);
167                                 DbgPrint("widget_resize returns: %d\n", tmp);
168                                 if (tmp == (int)WIDGET_ERROR_NONE) {
169                                         /*!
170                                          * \note
171                                          * Just returns resized canvas size.
172                                          * Even if it is not ready to render contents.
173                                          * Provider will allocate render buffer using this size.
174                                          */
175                                         *width = arg->info.widget_create.width;
176                                         *height = arg->info.widget_create.height;
177                                 }
178                         }
179                 }
180
181                 arg->info.widget_create.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
182         } else {
183                 ErrPrint("widget_create returns %d\n", ret);
184         }
185
186         if (widget_is_all_paused()) {
187                 DbgPrint("Box is paused\n");
188                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
189         }
190
191         return ret;
192 }
193
194 static int method_renew(struct widget_event_arg *arg, void *data)
195 {
196         int ret;
197         int w;
198         int h;
199         double priority;
200         struct widget_create_arg _arg;
201
202         DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s]\n",
203                         arg->pkgname, arg->id,
204                         arg->info.widget_recreate.content,
205                         arg->info.widget_recreate.timeout,
206                         arg->info.widget_recreate.has_script,
207                         arg->info.widget_recreate.period,
208                         arg->info.widget_recreate.cluster,
209                         arg->info.widget_recreate.category,
210                         arg->info.widget_recreate.abi);
211
212         if (!arg->info.widget_recreate.content || !strlen(arg->info.widget_recreate.content)) {
213                 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
214                 arg->info.widget_recreate.content = WIDGET_CONF_DEFAULT_CONTENT;
215         }
216
217         _arg.content = arg->info.widget_recreate.content;
218         _arg.timeout = arg->info.widget_recreate.timeout;
219         _arg.has_widget_script = arg->info.widget_recreate.has_script;
220         _arg.period = arg->info.widget_recreate.period;
221         _arg.cluster = arg->info.widget_recreate.cluster;
222         _arg.category = arg->info.widget_recreate.category;
223         _arg.abi = arg->info.widget_recreate.abi;
224         _arg.skip_need_to_create = 1;
225         _arg.direct_addr = arg->info.widget_recreate.direct_addr;
226
227         invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
228
229         ret = widget_create(arg->pkgname, arg->id,
230                         &_arg,
231                         &w, &h, &priority,
232                         &arg->info.widget_recreate.out_content,
233                         &arg->info.widget_recreate.out_title);
234         if (ret == 0) {
235                 if (w != arg->info.widget_recreate.width || h != arg->info.widget_recreate.height) {
236                         int tmp;
237                         tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_recreate.width, arg->info.widget_recreate.height);
238                         if (tmp < 0) {
239                                 DbgPrint("Resize[%dx%d] returns: %d\n", arg->info.widget_recreate.width, arg->info.widget_recreate.height, tmp);
240                         }
241                 } else {
242                         DbgPrint("No need to change the size: %dx%d\n", w, h);
243                 }
244
245                 arg->info.widget_recreate.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
246         } else {
247                 ErrPrint("widget_create returns %d\n", ret);
248         }
249
250         if (widget_is_all_paused()) {
251                 DbgPrint("Box is paused\n");
252                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
253         }
254
255         return ret;
256 }
257
258 static int method_delete(struct widget_event_arg *arg, void *data)
259 {
260         int ret;
261
262         DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
263
264         if (arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_DEFAULT || arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_UNINSTALL) {
265                 DbgPrint("Box is deleted from the viewer\n");
266                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_DELETED);
267         }
268
269         invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
270         ret = widget_destroy(arg->pkgname, arg->id, 0);
271         return ret;
272 }
273
274 static int method_content_event(struct widget_event_arg *arg, void *data)
275 {
276         int ret;
277         struct widget_event_info info;
278
279         info = arg->info.content_event.info;
280
281         ret = widget_script_event(arg->pkgname, arg->id,
282                         arg->info.content_event.signal_name, arg->info.content_event.source,
283                         &info);
284         return ret;
285 }
286
287 static int method_clicked(struct widget_event_arg *arg, void *data)
288 {
289         int ret;
290
291         DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
292                         arg->pkgname, arg->id,
293                         arg->info.clicked.event, arg->info.clicked.timestamp,
294                         arg->info.clicked.x, arg->info.clicked.y);
295         ret = widget_clicked(arg->pkgname, arg->id,
296                         arg->info.clicked.event,
297                         arg->info.clicked.timestamp, arg->info.clicked.x, arg->info.clicked.y);
298
299         return ret;
300 }
301
302 static int method_text_signal(struct widget_event_arg *arg, void *data)
303 {
304         int ret;
305         struct widget_event_info info;
306
307         info = arg->info.text_signal.info;
308
309         DbgPrint("pkgname[%s] id[%s] signal_name[%s] source[%s]\n", arg->pkgname, arg->id, arg->info.text_signal.signal_name, arg->info.text_signal.source);
310         ret = widget_script_event(arg->pkgname, arg->id,
311                         arg->info.text_signal.signal_name, arg->info.text_signal.source,
312                         &info);
313
314         return ret;
315 }
316
317 static int method_resize(struct widget_event_arg *arg, void *data)
318 {
319         int ret;
320
321         invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
322
323         DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
324         ret = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
325
326         return ret;
327 }
328
329 static int method_set_period(struct widget_event_arg *arg, void *data)
330 {
331         int ret;
332         DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
333         ret = widget_viewer_set_period(arg->pkgname, arg->id, arg->info.set_period.period);
334         return ret;
335 }
336
337 static int method_change_group(struct widget_event_arg *arg, void *data)
338 {
339         int ret;
340         DbgPrint("pkgname[%s] id[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
341         ret = widget_change_group(arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
342         return ret;
343 }
344
345 static int method_pinup(struct widget_event_arg *arg, void *data)
346 {
347         DbgPrint("pkgname[%s] id[%s] state[%d]\n", arg->pkgname, arg->id, arg->info.pinup.state);
348         arg->info.pinup.content_info = widget_pinup(arg->pkgname, arg->id, arg->info.pinup.state);
349         return arg->info.pinup.content_info ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_SUPPORTED;
350 }
351
352 static int method_update_content(struct widget_event_arg *arg, void *data)
353 {
354         int ret;
355
356         if (!arg->id || !strlen(arg->id)) {
357                 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
358                         DbgPrint("pkgname[%s] content[%s]\n", arg->pkgname, arg->info.update_content.content);
359                         ret = widget_set_content_info_all(arg->pkgname, arg->info.update_content.content);
360                 } else {
361                         DbgPrint("pkgname[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category);
362                         ret = widget_update_all(arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category, arg->info.update_content.force);
363                 }
364         } else {
365                 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
366                         DbgPrint("id[%s] content[%s]\n", arg->id, arg->info.update_content.content);
367                         ret = widget_set_content_info(arg->pkgname, arg->id, arg->info.update_content.content);
368                 } else {
369                         DbgPrint("Update [%s]\n", arg->id);
370                         ret = widget_update(arg->pkgname, arg->id, arg->info.update_content.force);
371                 }
372         }
373
374         return ret;
375 }
376
377 static int method_pause(struct widget_event_arg *arg, void *data)
378 {
379         widget_pause_all();
380
381         if (s_info.ping_timer) {
382                 ecore_timer_freeze(s_info.ping_timer);
383         }
384
385         if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
386                 elm_cache_all_flush();
387                 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
388                 malloc_trim(0);
389         }
390
391         return WIDGET_ERROR_NONE;
392 }
393
394 static int method_resume(struct widget_event_arg *arg, void *data)
395 {
396         widget_resume_all();
397
398         if (s_info.ping_timer) {
399                 ecore_timer_thaw(s_info.ping_timer);
400         }
401
402         return WIDGET_ERROR_NONE;
403 }
404
405 static Eina_Bool send_ping_cb(void *data)
406 {
407         widget_provider_send_ping();
408         return ECORE_CALLBACK_RENEW;
409 }
410
411 static int method_disconnected(struct widget_event_arg *arg, void *data)
412 {
413         if (s_info.ping_timer) {
414                 ecore_timer_del(s_info.ping_timer);
415                 s_info.ping_timer = NULL;
416         }
417
418         main_app_exit();
419         return WIDGET_ERROR_NONE;
420 }
421
422 static int method_connected(struct widget_event_arg *arg, void *data)
423 {
424         int ret;
425         ret = widget_provider_send_hello();
426         if (ret == 0) {
427                 double ping_interval;
428
429                 ping_interval = WIDGET_CONF_DEFAULT_PING_TIME / 2.0f;
430                 DbgPrint("Ping Timer: %lf\n", ping_interval);
431
432                 s_info.ping_timer = ecore_timer_add(ping_interval, send_ping_cb, NULL);
433                 if (!s_info.ping_timer) {
434                         ErrPrint("Failed to add a ping timer\n");
435                 }
436         }
437
438         return WIDGET_ERROR_NONE;
439 }
440
441 static int method_gbar_created(struct widget_event_arg *arg, void *data)
442 {
443         int ret;
444
445         ret = widget_open_gbar(arg->pkgname, arg->id);
446         if (ret < 0) {
447                 DbgPrint("%s Open PD: %d\n", arg->id, ret);
448         }
449
450         return WIDGET_ERROR_NONE;
451 }
452
453 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
454 {
455         int ret;
456
457         ret = widget_close_gbar(arg->pkgname, arg->id);
458         if (ret < 0) {
459                 DbgPrint("%s Close PD: %d\n", arg->id, ret);
460         }
461
462         return WIDGET_ERROR_NONE;
463 }
464
465 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
466 {
467         int ret;
468         struct widget_event_info info;
469
470         memset(&info, 0, sizeof(info));
471         info.pointer.x = arg->info.gbar_move.x;
472         info.pointer.y = arg->info.gbar_move.y;
473         info.pointer.down = 0;
474
475         ret = widget_script_event(arg->pkgname, arg->id,
476                         "gbar,move", util_uri_to_path(arg->id), &info);
477         return ret;
478 }
479
480 static int method_widget_pause(struct widget_event_arg *arg, void *data)
481 {
482         int ret;
483
484         ret = widget_pause(arg->pkgname, arg->id);
485
486         if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
487                 elm_cache_all_flush();
488                 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
489                 malloc_trim(0);
490         }
491
492         return ret;
493 }
494
495 static int method_widget_resume(struct widget_event_arg *arg, void *data)
496 {
497         return widget_resume(arg->pkgname, arg->id);
498 }
499
500 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
501 {
502         return widget_viewer_connected(arg->pkgname, arg->id, arg->info.viewer_connected.direct_addr);
503 }
504
505 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
506 {
507         return widget_viewer_disconnected(arg->pkgname, arg->id, arg->info.viewer_disconnected.direct_addr);
508 }
509
510 static int method_orientation(struct widget_event_arg *arg, void *data)
511 {
512         invoke_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, arg->id);
513         return widget_set_orientation(arg->pkgname, arg->id, arg->info.orientation.degree);
514 }
515
516 HAPI int client_init(const char *name, const char *abi, const char *accel, int secured)
517 {
518         struct widget_event_table table = {
519                 .widget_create = method_new,
520                 .widget_recreate = method_renew,
521                 .widget_destroy = method_delete,
522                 .content_event = method_content_event,
523                 .clicked = method_clicked,
524                 .text_signal = method_text_signal,
525                 .resize = method_resize,
526                 .set_period = method_set_period,
527                 .change_group = method_change_group,
528                 .pinup = method_pinup,
529                 .update_content = method_update_content,
530                 .pause = method_pause,
531                 .resume = method_resume,
532                 .disconnected = method_disconnected,
533                 .connected = method_connected,
534                 .gbar_create = method_gbar_created,
535                 .gbar_destroy = method_gbar_destroyed,
536                 .gbar_move = method_gbar_moved,
537                 .widget_pause = method_widget_pause,
538                 .widget_resume = method_widget_resume,
539                 .viewer_connected = method_viewer_connected,
540                 .viewer_disconnected = method_viewer_disconnected,
541                 .orientation = method_orientation,
542         };
543
544         widget_provider_prepare_init(abi, accel, secured);
545         return widget_provider_init(util_screen_get(), name, &table, NULL, 1, 1);
546 }
547
548 HAPI int client_fini(void)
549 {
550         (void)widget_provider_fini();
551         return WIDGET_ERROR_NONE;
552 }
553
554 /* End of a file */
555