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 ERR("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));
81 return CALENDAR_ERROR_OUT_OF_MEMORY;
83 sender->name = cal_strdup(name);
84 DBG("[SENDER] Append sender[%s]", sender->name);
85 cal_sender_list = g_list_append(cal_sender_list, sender);
86 return CALENDAR_ERROR_NONE;
89 static gboolean _handle_register_resource(calDbus *object,
90 GDBusMethodInvocation *invocation)
95 const char *sender_name = NULL;
96 sender_name = g_dbus_method_invocation_get_sender(invocation);
98 g_mutex_lock(&cal_server_dbus_sender);
99 if (true == _has_sender(sender_name, NULL)) {
100 ERR("Already has sender");
101 g_mutex_unlock(&cal_server_dbus_sender);
104 ret = _append_sender(sender_name);
105 if (CALENDAR_ERROR_NONE != ret) {
106 ERR("_append_sender() Fail");
107 g_mutex_unlock(&cal_server_dbus_sender);
110 DBG("append sender");
111 g_mutex_unlock(&cal_server_dbus_sender);
113 cal_dbus_complete_register_resource(object, invocation, ret);
118 static gboolean _handle_unregister_resource(calDbus *object,
119 GDBusMethodInvocation *invocation)
124 const char *sender_name = NULL;
125 sender_name = g_dbus_method_invocation_get_sender(invocation);
127 GList *cursor = NULL;
128 g_mutex_lock(&cal_server_dbus_sender);
129 if (true == _has_sender(sender_name, &cursor)) {
130 DBG("[SENDER] delete sender[%s]", sender_name);
131 cal_sender_s *sender = (cal_sender_s *)cursor->data;
134 cal_sender_list = g_list_delete_link(cal_sender_list, cursor);
137 if (0 == g_list_length(cal_sender_list)) {
138 DBG("sender list is 0");
139 g_list_free_full(cal_sender_list, free);
140 cal_sender_list = NULL;
142 g_mutex_unlock(&cal_server_dbus_sender);
144 cal_dbus_complete_unregister_resource(object, invocation, ret);
149 static gboolean _handle_insert_record(calDbus *object, GDBusMethodInvocation *invocation,
150 GVariant *arg_handle, GVariant *arg_record)
153 calendar_record_h record = NULL;
154 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
157 ret = cal_db_insert_record(record, &id);
160 version = cal_db_util_get_transaction_ver();
161 cal_dbus_complete_insert_record(object, invocation, id, version, ret);
162 calendar_record_destroy(record, true);
164 cal_server_ondemand_start();
168 static gboolean _handle_update_record(calDbus *object, GDBusMethodInvocation *invocation,
169 GVariant *arg_handle, GVariant *arg_record)
172 calendar_record_h record = NULL;
173 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
175 ret = cal_db_update_record(record);
178 version = cal_db_util_get_transaction_ver();
179 cal_dbus_complete_update_record(object, invocation, version, ret);
180 calendar_record_destroy(record, true);
182 cal_server_ondemand_start();
186 static gboolean _handle_delete_record(calDbus *object, GDBusMethodInvocation *invocation,
187 GVariant *arg_handle, char *view_uri, int id)
190 ret = cal_db_delete_record(view_uri, id);
193 version = cal_db_util_get_transaction_ver();
194 cal_dbus_complete_delete_record(object, invocation, version, ret);
196 cal_server_ondemand_start();
200 static gboolean _handle_replace_record(calDbus *object, GDBusMethodInvocation *invocation,
201 GVariant *arg_handle, GVariant *arg_record, int id)
204 calendar_record_h record = NULL;
205 ret = cal_dbus_utils_gvariant_to_record(arg_record, &record);
207 ret = cal_db_replace_record(record, id);
210 version = cal_db_util_get_transaction_ver();
211 cal_dbus_complete_replace_record(object, invocation, version, ret);
212 calendar_record_destroy(record, true);
214 cal_server_ondemand_start();
218 static gboolean _handle_insert_records(calDbus *object, GDBusMethodInvocation *invocation,
219 GVariant *arg_handle, GVariant *arg_list)
222 calendar_list_h list = NULL;
223 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
227 ret = cal_db_insert_records(list, &ids, &count);
228 calendar_list_destroy(list, true);
231 version = cal_db_util_get_transaction_ver();
232 GVariant *arg_ids = cal_dbus_utils_ids_to_gvariant(ids, count);
233 cal_dbus_complete_insert_records(object, invocation, arg_ids, count, version, ret);
236 g_variant_unref(arg_ids);
238 cal_server_ondemand_start();
242 static gboolean _handle_update_records(calDbus *object, GDBusMethodInvocation *invocation,
243 GVariant *arg_handle, GVariant *arg_list)
246 calendar_list_h list = NULL;
247 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
249 ret = cal_db_update_records(list);
250 calendar_list_destroy(list, true);
253 version = cal_db_util_get_transaction_ver();
254 cal_dbus_complete_update_records(object, invocation, version, ret);
256 cal_server_ondemand_start();
260 static gboolean _handle_delete_records(calDbus *object, GDBusMethodInvocation *invocation,
261 GVariant *arg_handle, char *view_uri, GVariant *arg_ids, int count)
265 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
267 ret = cal_db_delete_records(view_uri, ids, count);
270 version = cal_db_util_get_transaction_ver();
271 cal_dbus_complete_delete_records(object, invocation, version, ret);
274 cal_server_ondemand_start();
278 static gboolean _handle_replace_records(calDbus *object, GDBusMethodInvocation *invocation,
279 GVariant *arg_handle, GVariant *arg_list, GVariant *arg_ids, int count)
282 calendar_list_h list = NULL;
284 ret = cal_dbus_utils_gvariant_to_list(arg_list, &list);
285 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
287 ret = cal_db_replace_records(list, ids, count);
289 calendar_list_destroy(list, true);
292 version = cal_db_util_get_transaction_ver();
293 cal_dbus_complete_replace_records(object, invocation, version, ret);
295 cal_server_ondemand_start();
299 static gboolean _handle_get_record(calDbus *object, GDBusMethodInvocation *invocation,
300 GVariant *arg_handle, char *view_uri, int id)
303 calendar_record_h record = NULL;
304 ret = cal_db_get_record(view_uri, id, &record);
306 GVariant *arg_record = cal_dbus_utils_record_to_gvariant(record);
307 cal_dbus_complete_get_record(object, invocation, arg_record, ret);
308 g_variant_unref(arg_record);
309 calendar_record_destroy(record, true);
311 cal_server_ondemand_start();
315 static gboolean _handle_get_all_records(calDbus *object, GDBusMethodInvocation *invocation,
316 GVariant *arg_handle, char *view_uri, int offset, int limit)
321 calendar_list_h list = NULL;
322 ret = cal_db_get_all_records(view_uri, offset, limit, &list);
324 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
325 cal_dbus_complete_get_all_records(object, invocation, arg_list, ret);
326 calendar_list_destroy(list, true);
327 g_variant_unref(arg_list);
329 cal_server_ondemand_start();
333 static gboolean _handle_get_records_with_query(calDbus *object, GDBusMethodInvocation *invocation,
334 GVariant *arg_handle, GVariant *arg_query, int offset, int limit)
337 calendar_query_h query = NULL;
338 ret = cal_dbus_utils_gvariant_to_query(arg_query, &query);
340 calendar_list_h list = NULL;
341 ret = cal_db_get_records_with_query(query, offset, limit, &list);
343 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
344 cal_dbus_complete_get_records_with_query(object, invocation, arg_list, ret);
345 g_variant_unref(arg_list);
346 calendar_list_destroy(list, true);
348 cal_server_ondemand_start();
352 static gboolean _handle_get_count(calDbus *object, GDBusMethodInvocation *invocation,
353 GVariant *arg_handle, char *view_uri)
357 ret = cal_db_get_count(view_uri, &count);
359 cal_dbus_complete_get_count(object, invocation, count, ret);
361 cal_server_ondemand_start();
365 static gboolean _handle_get_count_with_query(calDbus *object, GDBusMethodInvocation *invocation,
366 GVariant *arg_handle, GVariant *arg_query)
369 calendar_query_h query = NULL;
370 ret = cal_dbus_utils_gvariant_to_query(arg_query, &query);
373 ret = cal_db_get_count_with_query(query, &count);
374 cal_dbus_complete_get_count_with_query(object, invocation, count, ret);
376 cal_server_ondemand_start();
380 static gboolean _handle_get_current_version(calDbus *object, GDBusMethodInvocation *invocation,
381 GVariant *arg_handle)
385 ret = cal_db_get_current_version(&version);
387 cal_dbus_complete_get_current_version(object, invocation, version, ret);
389 cal_server_ondemand_start();
393 static gboolean _handle_check_permission_write(calDbus *object, GDBusMethodInvocation *invocation)
395 cal_dbus_complete_check_permission_write(object, invocation);
396 cal_server_ondemand_start();
400 static gboolean _handle_check_permission_read(calDbus *object, GDBusMethodInvocation *invocation)
402 cal_dbus_complete_check_permission_read(object, invocation);
403 cal_server_ondemand_start();
407 static gboolean _handle_get_changes_by_version(calDbus *object, GDBusMethodInvocation *invocation,
408 GVariant *arg_handle, char *view_uri, int book_id, int in_version)
411 calendar_list_h list = NULL;
413 ret = cal_db_get_changes_by_version(view_uri, book_id, in_version, &list, &out_version);
415 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
416 cal_dbus_complete_get_changes_by_version(object, invocation, arg_list, out_version, ret);
417 calendar_list_destroy(list, true);
418 g_variant_unref(arg_list);
420 cal_server_ondemand_start();
424 static gboolean _handle_get_changes_exception_by_version(calDbus *object,
425 GDBusMethodInvocation *invocation,
426 GVariant *arg_handle,
432 calendar_list_h list = NULL;
433 ret = cal_db_get_changes_exception_by_version(view_uri, original_id, version, &list);
435 GVariant *arg_list = cal_dbus_utils_list_to_gvariant(list);
436 cal_dbus_complete_get_changes_exception_by_version(object, invocation, arg_list, ret);
437 calendar_list_destroy(list, true);
438 g_variant_unref(arg_list);
440 cal_server_ondemand_start();
444 static gboolean _handle_clean_after_sync(calDbus *object, GDBusMethodInvocation *invocation,
445 GVariant *arg_handle, int book_id, int version)
448 ret = cal_db_clean_after_sync(book_id, version);
450 cal_dbus_complete_clean_after_sync(object, invocation, ret);
452 cal_server_ondemand_start();
456 static gboolean _handle_insert_vcalendars(calDbus *object, GDBusMethodInvocation *invocation,
457 GVariant *arg_handle, char *stream)
462 ret = cal_db_insert_vcalendars(stream, &ids, &count);
464 GVariant *arg_ids = cal_dbus_utils_ids_to_gvariant(ids, count);
467 version = cal_db_util_get_transaction_ver();
468 cal_dbus_complete_insert_vcalendars(object, invocation, arg_ids, count, version, ret);
470 g_variant_unref(arg_ids);
472 cal_server_ondemand_start();
476 static gboolean _handle_replace_vcalendars(calDbus *object, GDBusMethodInvocation *invocation,
477 GVariant *arg_handle, char *stream, GVariant *arg_ids, int count)
481 ret = cal_dbus_utils_gvariant_to_ids(arg_ids, count, &ids);
483 ret = cal_db_replace_vcalendars(stream, ids, count);
486 version = cal_db_util_get_transaction_ver();
487 cal_dbus_complete_replace_vcalendars(object, invocation, ret, version);
490 cal_server_ondemand_start();
494 static int _cal_server_dbus_find_sender(const char *owner_name, cal_sender_s **out_sender)
496 GList *cursor = NULL;
498 RETV_IF(NULL == owner_name, CALENDAR_ERROR_INVALID_PARAMETER);
499 RETV_IF(NULL == out_sender, CALENDAR_ERROR_INVALID_PARAMETER);
501 cursor = cal_sender_list;
503 cal_sender_s *sender = (cal_sender_s *)cursor->data;
504 if (NULL == sender) {
505 ERR("sender is NULL");
506 return CALENDAR_ERROR_NO_DATA;
509 if (CAL_STRING_EQUAL == g_strcmp0(sender->name, owner_name)) {
510 *out_sender = sender;
513 cursor = g_list_next(cursor);
516 return CALENDAR_ERROR_NONE;
519 static void _delete_sender(cal_sender_s *sender)
521 RET_IF(NULL == sender);
523 GList *cursor = cal_sender_list;
525 if (cursor->data == sender) {
526 DBG("[SENDER] Delete sender[%s]", sender->name);
529 cal_sender_list = g_list_delete_link(cal_sender_list, cursor);
532 cursor = g_list_next(cursor);
536 static void _cal_server_dbus_name_owner_changed_cb(GDBusConnection *connection,
537 const gchar *sender_name,
538 const gchar *object_path,
539 const gchar *interface_name,
540 const gchar *signal_name,
541 GVariant *parameters,
548 gchar *old_owner = NULL;
549 gchar *new_owner = NULL;
551 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
552 DBG("name[%s] old_owner[%s] new_owner[%s]", name, old_owner, new_owner);
554 if (0 != strlen(new_owner)) {
555 DBG("new_owner[%s]", new_owner);
558 g_mutex_lock(&cal_server_dbus_sender);
559 /* empty new_owner means server-kill */
560 cal_sender_s *sender = NULL;
561 ret = _cal_server_dbus_find_sender(old_owner, &sender);
562 if (CALENDAR_ERROR_NONE != ret) {
563 ERR("_cal_server_dbus_find_sender() Fail(%d)", ret);
564 g_mutex_unlock(&cal_server_dbus_sender);
568 if (sender) { /* found bus name in our bus list */
569 DBG("owner[%s] stopped", old_owner);
570 _delete_sender(sender);
572 g_mutex_unlock(&cal_server_dbus_sender);
575 static int _cal_server_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
580 id = g_dbus_connection_signal_subscribe(conn,
581 "org.freedesktop.DBus", /* bus name */
582 "org.freedesktop.DBus", /* interface */
583 "NameOwnerChanged", /* member */
584 "/org/freedesktop/DBus", /* path */
586 G_DBUS_SIGNAL_FLAGS_NONE,
587 _cal_server_dbus_name_owner_changed_cb,
591 ERR("g_dbus_connection_signal_subscribe() Fail");
592 return CALENDAR_ERROR_IPC;
594 return CALENDAR_ERROR_NONE;
597 static void _dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
600 GError *error = NULL;
602 dbus_object = cal_dbus_skeleton_new();
603 if (NULL == dbus_object) {
604 ERR("cal_dbus_skeleton_new() Fail");
608 g_signal_connect(dbus_object, "handle-register-resource",
609 G_CALLBACK(_handle_register_resource), NULL);
610 g_signal_connect(dbus_object, "handle-unregister-resource",
611 G_CALLBACK(_handle_unregister_resource), NULL);
612 g_signal_connect(dbus_object, "handle-insert-record",
613 G_CALLBACK(_handle_insert_record), NULL);
614 g_signal_connect(dbus_object, "handle-update-record",
615 G_CALLBACK(_handle_update_record), NULL);
616 g_signal_connect(dbus_object, "handle-delete-record",
617 G_CALLBACK(_handle_delete_record), NULL);
618 g_signal_connect(dbus_object, "handle-replace-record",
619 G_CALLBACK(_handle_replace_record), NULL);
620 g_signal_connect(dbus_object, "handle-insert-records",
621 G_CALLBACK(_handle_insert_records), NULL);
622 g_signal_connect(dbus_object, "handle-update-records",
623 G_CALLBACK(_handle_update_records), NULL);
624 g_signal_connect(dbus_object, "handle-delete-records",
625 G_CALLBACK(_handle_delete_records), NULL);
626 g_signal_connect(dbus_object, "handle-replace-records",
627 G_CALLBACK(_handle_replace_records), NULL);
628 g_signal_connect(dbus_object, "handle-get-record",
629 G_CALLBACK(_handle_get_record), NULL);
630 g_signal_connect(dbus_object, "handle-get-all-records",
631 G_CALLBACK(_handle_get_all_records), NULL);
632 g_signal_connect(dbus_object, "handle-get-records-with-query",
633 G_CALLBACK(_handle_get_records_with_query), NULL);
634 g_signal_connect(dbus_object, "handle-get-count",
635 G_CALLBACK(_handle_get_count), NULL);
636 g_signal_connect(dbus_object, "handle-get-count-with-query",
637 G_CALLBACK(_handle_get_count_with_query), NULL);
638 g_signal_connect(dbus_object, "handle-get-current-version",
639 G_CALLBACK(_handle_get_current_version), NULL);
640 g_signal_connect(dbus_object, "handle-check-permission-write",
641 G_CALLBACK(_handle_check_permission_write), NULL);
642 g_signal_connect(dbus_object, "handle-check-permission-read",
643 G_CALLBACK(_handle_check_permission_read), NULL);
644 g_signal_connect(dbus_object, "handle-get-changes-by-version",
645 G_CALLBACK(_handle_get_changes_by_version), NULL);
646 g_signal_connect(dbus_object, "handle-get-changes-exception-by-version",
647 G_CALLBACK(_handle_get_changes_exception_by_version), NULL);
648 g_signal_connect(dbus_object, "handle-clean-after-sync",
649 G_CALLBACK(_handle_clean_after_sync), NULL);
650 g_signal_connect(dbus_object, "handle-insert-vcalendars",
651 G_CALLBACK(_handle_insert_vcalendars), NULL);
652 g_signal_connect(dbus_object, "handle-replace-vcalendars",
653 G_CALLBACK(_handle_replace_vcalendars), NULL);
655 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(dbus_object),
656 conn, CAL_DBUS_OBJPATH, &error);
658 ERR("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
663 ret = _cal_server_dbus_subscribe_name_owner_changed(conn);
664 if (CALENDAR_ERROR_NONE != ret) {
665 ERR("_cal_server_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
670 static void _dbus_on_name_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
672 DBG("Acquired the name %s", name);
675 static void _dbus_on_name_lost(GDBusConnection *conn, const gchar *name, gpointer user_data)
677 DBG("Lost the name %s", name);
680 unsigned int cal_server_dbus_init(void)
683 id = g_bus_own_name(G_BUS_TYPE_SESSION,
685 G_BUS_NAME_OWNER_FLAGS_REPLACE,
686 _dbus_on_bus_acquired,
687 _dbus_on_name_acquired,
692 ERR("g_bus_own_name() Fail");
698 void cal_server_dbus_deinit(unsigned int id)
700 g_bus_unown_name(id);
703 int cal_dbus_emit_signal(const char *dest, const char *signal_name, GVariant *value)
708 GError *error = NULL;
710 DBG("signal_name[%s]", signal_name);
711 DBG("data[%s]", g_variant_print(value, FALSE));
713 calDbusSkeleton *skeleton = NULL;
714 skeleton = CAL_DBUS_SKELETON(cal_dbus_get_object());
715 if (NULL == skeleton) {
716 ERR("cal_dbus_get_object() Fail");
717 return CALENDAR_ERROR_IPC;
720 GDBusConnection *conn = NULL;
721 conn = g_dbus_interface_skeleton_get_connection(G_DBUS_INTERFACE_SKELETON(skeleton));
723 ERR("g_dbus_interface_skeleton_get_connection() Fail");
724 return CALENDAR_ERROR_IPC;
727 ret = g_dbus_connection_emit_signal(conn,
736 ERR("g_dbus_connection_emit_signal() Fail");
738 ERR("error[%s]", error->message);
741 return CALENDAR_ERROR_IPC;
744 if (FALSE == g_dbus_connection_flush_sync(conn, NULL, &error)) {
745 ERR("g_dbus_connection_flush_sync() Fail");
747 ERR("error[%s]", error->message);
750 return CALENDAR_ERROR_IPC;
753 return CALENDAR_ERROR_NONE;
756 int cal_dbus_publish_reminder(int stream_size, char *stream)
760 GVariant *value = NULL;
761 value = cal_dbus_utils_stream_to_gvariant(stream_size, stream);
762 cal_dbus_emit_signal(NULL, CAL_NOTI_REMINDER_CAHNGED, value);
764 return CALENDAR_ERROR_NONE;