4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include "cal_internal.h"
25 #include "cal_typedef.h"
26 #include "cal_handle.h"
27 #include "cal_dbus_helper.h"
30 #include "cal_db_util.h"
31 #include "cal_server_dbus.h"
32 #include "cal_utils.h"
33 #include "cal_server_ondemand.h"
35 static calDbus *dbus_object = NULL;
36 static GMutex cal_server_dbus_sender;
37 static GList *cal_sender_list; /* global list to care resource handle for each sender bus */
39 typedef struct _cal_sender {
43 calDbus* cal_dbus_get_object(void)
48 static bool _has_sender(const char *name, GList **out_cursor)
50 bool has_sender = false;
53 cursor = cal_sender_list;
55 cal_sender_s *sender = (cal_sender_s *)cursor->data;
57 WARN("sender is NULL");
58 cursor = g_list_next(cursor);
61 if (CAL_STRING_EQUAL == g_strcmp0(sender->name, name)) {
62 DBG("found sender[%s]", name);
68 cursor = g_list_next(cursor);
73 static int _append_sender(const char *name)
75 RETV_IF(NULL == name, CALENDAR_ERROR_INVALID_PARAMETER);
77 cal_sender_s *sender = NULL;
78 sender = calloc(1, sizeof(cal_sender_s));
82 return CALENDAR_ERROR_OUT_OF_MEMORY;
85 sender->name = cal_strdup(name);
86 DBG("[SENDER] Append sender[%s]", sender->name);
87 cal_sender_list = g_list_append(cal_sender_list, sender);
88 return CALENDAR_ERROR_NONE;
91 static gboolean _handle_register_resource(calDbus *object,
92 GDBusMethodInvocation *invocation)
97 const char *sender_name = NULL;
98 sender_name = g_dbus_method_invocation_get_sender(invocation);
100 g_mutex_lock(&cal_server_dbus_sender);
101 if (true == _has_sender(sender_name, NULL)) {
102 /* LCOV_EXCL_START */
103 ERR("Already has sender");
104 g_mutex_unlock(&cal_server_dbus_sender);
108 ret = _append_sender(sender_name);
109 if (CALENDAR_ERROR_NONE != ret) {
110 /* LCOV_EXCL_START */
111 ERR("_append_sender() Fail");
112 g_mutex_unlock(&cal_server_dbus_sender);
116 DBG("append sender");
117 g_mutex_unlock(&cal_server_dbus_sender);
119 cal_dbus_complete_register_resource(object, invocation, ret);
124 static gboolean _handle_unregister_resource(calDbus *object,
125 GDBusMethodInvocation *invocation)
130 const char *sender_name = NULL;
131 sender_name = g_dbus_method_invocation_get_sender(invocation);
133 GList *cursor = NULL;
134 g_mutex_lock(&cal_server_dbus_sender);
135 if (true == _has_sender(sender_name, &cursor)) {
136 DBG("[SENDER] delete sender[%s]", sender_name);
137 cal_sender_s *sender = (cal_sender_s *)cursor->data;
140 cal_sender_list = g_list_delete_link(cal_sender_list, cursor);
143 if (0 == g_list_length(cal_sender_list)) {
144 DBG("sender list is 0");
145 g_list_free_full(cal_sender_list, free);
146 cal_sender_list = NULL;
148 g_mutex_unlock(&cal_server_dbus_sender);
150 cal_dbus_complete_unregister_resource(object, invocation, ret);
155 static gboolean _handle_insert_record(calDbus *object, GDBusMethodInvocation *invocation,
156 GVariant *arg_handle, GVariant *arg_record)
159 calendar_record_h record = NULL;
160 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
163 ret = cal_db_insert_record(record, &id);
166 version = cal_db_util_get_transaction_ver();
167 cal_dbus_complete_insert_record(object, invocation, id, version, ret);
168 calendar_record_destroy(record, true);
170 cal_server_ondemand_start();
174 static gboolean _handle_update_record(calDbus *object, GDBusMethodInvocation *invocation,
175 GVariant *arg_handle, GVariant *arg_record)
178 calendar_record_h record = NULL;
179 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
181 ret = cal_db_update_record(record);
184 version = cal_db_util_get_transaction_ver();
185 cal_dbus_complete_update_record(object, invocation, version, ret);
186 calendar_record_destroy(record, true);
188 cal_server_ondemand_start();
192 static gboolean _handle_delete_record(calDbus *object, GDBusMethodInvocation *invocation,
193 GVariant *arg_handle, char *view_uri, int id)
196 ret = cal_db_delete_record(view_uri, id);
199 version = cal_db_util_get_transaction_ver();
200 cal_dbus_complete_delete_record(object, invocation, version, ret);
202 cal_server_ondemand_start();
206 static gboolean _handle_replace_record(calDbus *object, GDBusMethodInvocation *invocation,
207 GVariant *arg_handle, GVariant *arg_record, int id)
210 calendar_record_h record = NULL;
211 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
213 ret = cal_db_replace_record(record, id);
216 version = cal_db_util_get_transaction_ver();
217 cal_dbus_complete_replace_record(object, invocation, version, ret);
218 calendar_record_destroy(record, true);
220 cal_server_ondemand_start();
224 static gboolean _handle_insert_records(calDbus *object, GDBusMethodInvocation *invocation,
225 GVariant *arg_handle, GVariant *arg_list)
228 calendar_list_h list = NULL;
229 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
233 ret = cal_db_insert_records(list, &ids, &count);
234 calendar_list_destroy(list, true);
237 version = cal_db_util_get_transaction_ver();
238 GVariant *arg_ids = cal_dbus_utils_ids_to_gvariant(ids, count);
239 cal_dbus_complete_insert_records(object, invocation, arg_ids, count, version, ret);
243 cal_server_ondemand_start();
247 static gboolean _handle_update_records(calDbus *object, GDBusMethodInvocation *invocation,
248 GVariant *arg_handle, GVariant *arg_list)
251 calendar_list_h list = NULL;
252 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
254 ret = cal_db_update_records(list);
255 calendar_list_destroy(list, true);
258 version = cal_db_util_get_transaction_ver();
259 cal_dbus_complete_update_records(object, invocation, version, ret);
261 cal_server_ondemand_start();
265 static gboolean _handle_delete_records(calDbus *object, GDBusMethodInvocation *invocation,
266 GVariant *arg_handle, char *view_uri, GVariant *arg_ids, int count)
270 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
272 ret = cal_db_delete_records(view_uri, ids, count);
275 version = cal_db_util_get_transaction_ver();
276 cal_dbus_complete_delete_records(object, invocation, version, ret);
279 cal_server_ondemand_start();
283 static gboolean _handle_replace_records(calDbus *object, GDBusMethodInvocation *invocation,
284 GVariant *arg_handle, GVariant *arg_list, GVariant *arg_ids, int count)
287 calendar_list_h list = NULL;
289 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
290 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
292 ret = cal_db_replace_records(list, ids, count);
294 calendar_list_destroy(list, true);
297 version = cal_db_util_get_transaction_ver();
298 cal_dbus_complete_replace_records(object, invocation, version, ret);
300 cal_server_ondemand_start();
304 static gboolean _handle_get_record(calDbus *object, GDBusMethodInvocation *invocation,
305 GVariant *arg_handle, char *view_uri, int id)
308 calendar_record_h record = NULL;
309 ret = cal_db_get_record(view_uri, id, &record);
311 GVariant *arg_record = cal_dbus_utils_record_to_gvariant(record);
312 cal_dbus_complete_get_record(object, invocation, arg_record, ret);
313 calendar_record_destroy(record, true);
315 cal_server_ondemand_start();
319 static gboolean _handle_get_all_records(calDbus *object, GDBusMethodInvocation *invocation,
320 GVariant *arg_handle, char *view_uri, int offset, int limit)
325 calendar_list_h list = NULL;
326 ret = cal_db_get_all_records(view_uri, offset, limit, &list);
328 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
329 cal_dbus_complete_get_all_records(object, invocation, arg_list, ret);
330 calendar_list_destroy(list, true);
332 cal_server_ondemand_start();
336 static gboolean _handle_get_records_with_query(calDbus *object, GDBusMethodInvocation *invocation,
337 GVariant *arg_handle, GVariant *arg_query, int offset, int limit)
340 calendar_query_h query = NULL;
341 ret = cal_dbus_utils_gvariant_to_query(arg_query, &query);
343 calendar_list_h list = NULL;
344 ret = cal_db_get_records_with_query(query, offset, limit, &list);
345 calendar_query_destroy(query);
347 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
348 cal_dbus_complete_get_records_with_query(object, invocation, arg_list, ret);
349 calendar_list_destroy(list, true);
351 cal_server_ondemand_start();
355 static gboolean _handle_get_count(calDbus *object, GDBusMethodInvocation *invocation,
356 GVariant *arg_handle, char *view_uri)
360 ret = cal_db_get_count(view_uri, &count);
362 cal_dbus_complete_get_count(object, invocation, count, ret);
364 cal_server_ondemand_start();
368 static gboolean _handle_get_count_with_query(calDbus *object, GDBusMethodInvocation *invocation,
369 GVariant *arg_handle, GVariant *arg_query)
372 calendar_query_h query = NULL;
373 ret = cal_dbus_utils_gvariant_to_query(arg_query, &query);
376 ret = cal_db_get_count_with_query(query, &count);
377 calendar_query_destroy(query);
379 cal_dbus_complete_get_count_with_query(object, invocation, count, ret);
381 cal_server_ondemand_start();
385 static gboolean _handle_get_current_version(calDbus *object, GDBusMethodInvocation *invocation,
386 GVariant *arg_handle)
390 ret = cal_db_get_current_version(&version);
392 cal_dbus_complete_get_current_version(object, invocation, version, ret);
394 cal_server_ondemand_start();
398 static gboolean _handle_check_permission_write(calDbus *object, GDBusMethodInvocation *invocation)
400 cal_dbus_complete_check_permission_write(object, invocation);
401 cal_server_ondemand_start();
405 static gboolean _handle_check_permission_read(calDbus *object, GDBusMethodInvocation *invocation)
407 cal_dbus_complete_check_permission_read(object, invocation);
408 cal_server_ondemand_start();
412 static gboolean _handle_get_changes_by_version(calDbus *object, GDBusMethodInvocation *invocation,
413 GVariant *arg_handle, char *view_uri, int book_id, int in_version)
416 calendar_list_h list = NULL;
418 ret = cal_db_get_changes_by_version(view_uri, book_id, in_version, &list, &out_version);
420 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
421 cal_dbus_complete_get_changes_by_version(object, invocation, arg_list, out_version, ret);
422 calendar_list_destroy(list, true);
424 cal_server_ondemand_start();
428 static gboolean _handle_get_changes_exception_by_version(calDbus *object,
429 GDBusMethodInvocation *invocation,
430 GVariant *arg_handle,
436 calendar_list_h list = NULL;
437 ret = cal_db_get_changes_exception_by_version(view_uri, original_id, version, &list);
439 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
440 cal_dbus_complete_get_changes_exception_by_version(object, invocation, arg_list, ret);
441 calendar_list_destroy(list, true);
443 cal_server_ondemand_start();
447 static gboolean _handle_clean_after_sync(calDbus *object, GDBusMethodInvocation *invocation,
448 GVariant *arg_handle, int book_id, int version)
451 ret = cal_db_clean_after_sync(book_id, version);
453 cal_dbus_complete_clean_after_sync(object, invocation, ret);
455 cal_server_ondemand_start();
459 static gboolean _handle_insert_vcalendars(calDbus *object, GDBusMethodInvocation *invocation,
460 GVariant *arg_handle, char *stream)
465 ret = cal_db_insert_vcalendars(stream, &ids, &count);
467 GVariant *arg_ids = cal_dbus_utils_ids_to_gvariant(ids, count);
470 version = cal_db_util_get_transaction_ver();
471 cal_dbus_complete_insert_vcalendars(object, invocation, arg_ids, count, version, ret);
474 cal_server_ondemand_start();
478 static gboolean _handle_replace_vcalendars(calDbus *object, GDBusMethodInvocation *invocation,
479 GVariant *arg_handle, char *stream, GVariant *arg_ids, int count)
483 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
485 ret = cal_db_replace_vcalendars(stream, ids, count);
488 version = cal_db_util_get_transaction_ver();
489 cal_dbus_complete_replace_vcalendars(object, invocation, ret, version);
492 cal_server_ondemand_start();
496 static int _cal_server_dbus_find_sender(const char *owner_name, cal_sender_s **out_sender)
498 GList *cursor = NULL;
500 RETV_IF(NULL == owner_name, CALENDAR_ERROR_INVALID_PARAMETER);
501 RETV_IF(NULL == out_sender, CALENDAR_ERROR_INVALID_PARAMETER);
503 cursor = cal_sender_list;
505 cal_sender_s *sender = (cal_sender_s *)cursor->data;
506 if (NULL == sender) {
507 /* LCOV_EXCL_START */
508 ERR("sender is NULL");
509 return CALENDAR_ERROR_NO_DATA;
513 if (CAL_STRING_EQUAL == g_strcmp0(sender->name, owner_name)) {
514 *out_sender = sender;
517 cursor = g_list_next(cursor);
520 return CALENDAR_ERROR_NONE;
523 static gboolean _handle_link_record(calDbus *object, GDBusMethodInvocation *invocation,
524 GVariant *arg_handle, int base_id, int record_id)
529 ret = cal_db_link_record(base_id, record_id);
530 version = cal_db_util_get_transaction_ver();
531 cal_dbus_complete_link_record(object, invocation, ret, version);
533 cal_server_ondemand_start();
537 static gboolean _handle_unlink_record(calDbus *object, GDBusMethodInvocation *invocation,
538 GVariant *arg_handle, int record_id)
543 ret = cal_db_unlink_record(record_id);
544 version = cal_db_util_get_transaction_ver();
545 cal_dbus_complete_unlink_record(object, invocation, ret, version);
547 cal_server_ondemand_start();
551 static void _delete_sender(cal_sender_s *sender)
553 RET_IF(NULL == sender);
555 GList *cursor = cal_sender_list;
557 if (cursor->data == sender) {
558 DBG("[SENDER] Delete sender[%s]", sender->name);
561 cal_sender_list = g_list_delete_link(cal_sender_list, cursor);
564 cursor = g_list_next(cursor);
568 static void _cal_server_dbus_name_owner_changed_cb(GDBusConnection *connection,
569 const gchar *sender_name,
570 const gchar *object_path,
571 const gchar *interface_name,
572 const gchar *signal_name,
573 GVariant *parameters,
580 gchar *old_owner = NULL;
581 gchar *new_owner = NULL;
583 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
584 DBG("name[%s] old_owner[%s] new_owner[%s]", name, old_owner, new_owner);
586 if (0 != strlen(new_owner)) {
587 DBG("new_owner[%s]", new_owner);
590 g_mutex_lock(&cal_server_dbus_sender);
591 /* empty new_owner means server-kill */
592 cal_sender_s *sender = NULL;
593 ret = _cal_server_dbus_find_sender(old_owner, &sender);
594 if (CALENDAR_ERROR_NONE != ret) {
595 /* LCOV_EXCL_START */
596 ERR("_cal_server_dbus_find_sender() Fail(%d)", ret);
597 g_mutex_unlock(&cal_server_dbus_sender);
602 if (sender) { /* found bus name in our bus list */
603 DBG("owner[%s] stopped", old_owner);
604 _delete_sender(sender);
606 g_mutex_unlock(&cal_server_dbus_sender);
609 static int _cal_server_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
614 id = g_dbus_connection_signal_subscribe(conn,
615 "org.freedesktop.DBus", /* bus name */
616 "org.freedesktop.DBus", /* interface */
617 "NameOwnerChanged", /* member */
618 "/org/freedesktop/DBus", /* path */
620 G_DBUS_SIGNAL_FLAGS_NONE,
621 _cal_server_dbus_name_owner_changed_cb,
625 /* LCOV_EXCL_START */
626 ERR("g_dbus_connection_signal_subscribe() Fail");
627 return CALENDAR_ERROR_IPC;
630 return CALENDAR_ERROR_NONE;
633 static void _dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
636 GError *error = NULL;
638 dbus_object = cal_dbus_skeleton_new();
639 if (NULL == dbus_object) {
640 /* LCOV_EXCL_START */
641 ERR("cal_dbus_skeleton_new() Fail");
646 g_signal_connect(dbus_object, "handle-register-resource",
647 G_CALLBACK(_handle_register_resource), NULL);
648 g_signal_connect(dbus_object, "handle-unregister-resource",
649 G_CALLBACK(_handle_unregister_resource), NULL);
650 g_signal_connect(dbus_object, "handle-insert-record",
651 G_CALLBACK(_handle_insert_record), NULL);
652 g_signal_connect(dbus_object, "handle-update-record",
653 G_CALLBACK(_handle_update_record), NULL);
654 g_signal_connect(dbus_object, "handle-delete-record",
655 G_CALLBACK(_handle_delete_record), NULL);
656 g_signal_connect(dbus_object, "handle-replace-record",
657 G_CALLBACK(_handle_replace_record), NULL);
658 g_signal_connect(dbus_object, "handle-insert-records",
659 G_CALLBACK(_handle_insert_records), NULL);
660 g_signal_connect(dbus_object, "handle-update-records",
661 G_CALLBACK(_handle_update_records), NULL);
662 g_signal_connect(dbus_object, "handle-delete-records",
663 G_CALLBACK(_handle_delete_records), NULL);
664 g_signal_connect(dbus_object, "handle-replace-records",
665 G_CALLBACK(_handle_replace_records), NULL);
666 g_signal_connect(dbus_object, "handle-get-record",
667 G_CALLBACK(_handle_get_record), NULL);
668 g_signal_connect(dbus_object, "handle-get-all-records",
669 G_CALLBACK(_handle_get_all_records), NULL);
670 g_signal_connect(dbus_object, "handle-get-records-with-query",
671 G_CALLBACK(_handle_get_records_with_query), NULL);
672 g_signal_connect(dbus_object, "handle-get-count",
673 G_CALLBACK(_handle_get_count), NULL);
674 g_signal_connect(dbus_object, "handle-get-count-with-query",
675 G_CALLBACK(_handle_get_count_with_query), NULL);
676 g_signal_connect(dbus_object, "handle-get-current-version",
677 G_CALLBACK(_handle_get_current_version), NULL);
678 g_signal_connect(dbus_object, "handle-check-permission-write",
679 G_CALLBACK(_handle_check_permission_write), NULL);
680 g_signal_connect(dbus_object, "handle-check-permission-read",
681 G_CALLBACK(_handle_check_permission_read), NULL);
682 g_signal_connect(dbus_object, "handle-get-changes-by-version",
683 G_CALLBACK(_handle_get_changes_by_version), NULL);
684 g_signal_connect(dbus_object, "handle-get-changes-exception-by-version",
685 G_CALLBACK(_handle_get_changes_exception_by_version), NULL);
686 g_signal_connect(dbus_object, "handle-clean-after-sync",
687 G_CALLBACK(_handle_clean_after_sync), NULL);
688 g_signal_connect(dbus_object, "handle-insert-vcalendars",
689 G_CALLBACK(_handle_insert_vcalendars), NULL);
690 g_signal_connect(dbus_object, "handle-replace-vcalendars",
691 G_CALLBACK(_handle_replace_vcalendars), NULL);
692 g_signal_connect(dbus_object, "handle-link-record",
693 G_CALLBACK(_handle_link_record), NULL);
694 g_signal_connect(dbus_object, "handle-unlink-record",
695 G_CALLBACK(_handle_unlink_record), NULL);
697 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(dbus_object),
698 conn, CAL_DBUS_OBJPATH, &error);
700 /* LCOV_EXCL_START */
701 ERR("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
707 ret = _cal_server_dbus_subscribe_name_owner_changed(conn);
708 if (CALENDAR_ERROR_NONE != ret) {
709 /* LCOV_EXCL_START */
710 ERR("_cal_server_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
716 static void _dbus_on_name_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
718 DBG("Acquired the name %s", name);
721 static void _dbus_on_name_lost(GDBusConnection *conn, const gchar *name, gpointer user_data)
723 DBG("Lost the name %s", name);
726 unsigned int cal_server_dbus_init(void)
729 id = g_bus_own_name(G_BUS_TYPE_SESSION,
731 G_BUS_NAME_OWNER_FLAGS_REPLACE,
732 _dbus_on_bus_acquired,
733 _dbus_on_name_acquired,
738 /* LCOV_EXCL_START */
739 ERR("g_bus_own_name() Fail");
746 void cal_server_dbus_deinit(unsigned int id)
748 g_bus_unown_name(id);
751 int cal_dbus_emit_signal(const char *dest, const char *signal_name, GVariant *value)
756 GError *error = NULL;
758 DBG("signal_name[%s]", signal_name);
759 DBG("data[%s]", g_variant_print(value, FALSE));
761 calDbusSkeleton *skeleton = NULL;
762 skeleton = CAL_DBUS_SKELETON(cal_dbus_get_object());
763 if (NULL == skeleton) {
764 /* LCOV_EXCL_START */
765 ERR("cal_dbus_get_object() Fail");
766 return CALENDAR_ERROR_IPC;
770 GDBusConnection *conn = NULL;
771 conn = g_dbus_interface_skeleton_get_connection(G_DBUS_INTERFACE_SKELETON(skeleton));
773 /* LCOV_EXCL_START */
774 ERR("g_dbus_interface_skeleton_get_connection() Fail");
775 return CALENDAR_ERROR_IPC;
779 ret = g_dbus_connection_emit_signal(conn,
788 /* LCOV_EXCL_START */
789 ERR("g_dbus_connection_emit_signal() Fail");
791 ERR("error[%s]", error->message);
794 return CALENDAR_ERROR_IPC;
798 if (FALSE == g_dbus_connection_flush_sync(conn, NULL, &error)) {
799 /* LCOV_EXCL_START */
800 ERR("g_dbus_connection_flush_sync() Fail");
802 ERR("error[%s]", error->message);
805 return CALENDAR_ERROR_IPC;
809 return CALENDAR_ERROR_NONE;
812 int cal_dbus_publish_reminder(int stream_size, char *stream)
816 GVariant *value = NULL;
817 value = cal_dbus_utils_stream_to_gvariant(stream_size, stream);
818 cal_dbus_emit_signal(NULL, CAL_NOTI_REMINDER_CAHNGED, value);
820 return CALENDAR_ERROR_NONE;