sync with 2.4
[platform/core/pim/contacts-service.git] / client / ctsvc_client_noti.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <pims-ipc.h>
21 #include <pims-ipc-svc.h>
22 #include <pims-ipc-data.h>
23
24 #include "contacts.h"
25 #include "ctsvc_internal.h"
26 #include "ctsvc_ipc_define.h"
27 #include "ctsvc_mutex.h"
28 #include "ctsvc_client_ipc.h"
29
30 typedef struct
31 {
32         contacts_db_change_cb_with_info cb;
33         void *user_data;
34 }db_callback_info_s;
35
36 typedef struct
37 {
38         char *view_uri;
39         GSList *callbacks;
40 }subscribe_info_s;
41
42 static int __ipc_pubsub_ref = 0;
43 static pims_ipc_h __ipc = NULL;
44 static GSList *__db_change_subscribe_list = NULL;
45
46 static void __ctsvc_db_subscriber_callback(pims_ipc_h ipc, pims_ipc_data_h data, void *user_data)
47 {
48         unsigned int size = 0;
49         char *str = NULL;
50         subscribe_info_s *info = user_data;
51
52         if (data)
53                 str = (char*)pims_ipc_data_get(data, &size);
54
55         if (!str) {
56                 CTS_ERR("There is no changed data");
57                 return;
58         }
59
60         if (info) {
61                 GSList *l;
62                 for (l = info->callbacks;l;l=l->next) {
63                         db_callback_info_s *cb_info = l->data;
64                         if (cb_info->cb) {
65                                 cb_info->cb(info->view_uri, str, cb_info->user_data);
66                         }
67                 }
68         }
69 }
70
71 // This API should be called in CTS_MUTEX_PIMS_IPC_PUBSUB mutex
72 pims_ipc_h ctsvc_ipc_get_handle_for_change_subsciption()
73 {
74         return __ipc;
75 }
76
77 int ctsvc_ipc_create_for_change_subscription()
78 {
79         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
80
81         if (0 < __ipc_pubsub_ref) {
82                 __ipc_pubsub_ref++;
83                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
84                 return CONTACTS_ERROR_NONE;
85         }
86
87         if (!__ipc) {
88                 __ipc = pims_ipc_create_for_subscribe(CTSVC_IPC_SOCKET_PATH_FOR_CHANGE_SUBSCRIPTION);
89                 if (!__ipc) {
90                         CTS_ERR("pims_ipc_create_for_subscribe error\n");
91                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
92                         return CONTACTS_ERROR_IPC;
93                 }
94         }
95         __ipc_pubsub_ref++;
96         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
97         return CONTACTS_ERROR_NONE;
98 }
99
100 int ctsvc_ipc_destroy_for_change_subscription()
101 {
102         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
103
104         if (1 == __ipc_pubsub_ref) {
105                 pims_ipc_destroy_for_subscribe(__ipc);
106                 __ipc = NULL;
107         }
108         else if (1 < __ipc_pubsub_ref) {
109                 CTS_DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref);
110         }
111         else {
112                 CTS_DBG("System : please call connection APIs, connection count is (%d)", __ipc_pubsub_ref);
113                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
114                 return CONTACTS_ERROR_INVALID_PARAMETER;
115         }
116
117         __ipc_pubsub_ref--;
118
119         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
120         return CONTACTS_ERROR_NONE;
121 }
122
123 API int contacts_db_add_changed_cb_with_info(const char* view_uri,
124                 contacts_db_change_cb_with_info cb, void* user_data)
125 {
126         GSList *it = NULL;
127         subscribe_info_s *info = NULL;
128         db_callback_info_s *cb_info;
129         bool result = false;
130         int ret;
131
132         RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
133         RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
134
135         if (strncmp(view_uri, CTSVC_VIEW_URI_PHONELOG, strlen(CTSVC_VIEW_URI_PHONELOG)) == 0) {
136                 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_PHONELOG_READ, &result);
137                 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission fail (%d)", ret);
138                 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (phonelog read)");
139         }
140         else if (strncmp(view_uri, CTSVC_VIEW_URI_PERSON, strlen(CTSVC_VIEW_URI_PERSON)) == 0) {
141                 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
142                 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission fail (%d)", ret);
143                 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
144         }
145         else {
146                 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
147                 return CONTACTS_ERROR_INVALID_PARAMETER;
148         }
149
150         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
151
152         for (it=__db_change_subscribe_list;it;it=it->next) {
153                 if (!it->data) continue;
154
155                 info = it->data;
156                 if (strcmp(info->view_uri, view_uri) == 0)
157                         break;
158                 else
159                         info = NULL;
160         }
161
162         if (!info) {
163                 info = calloc(1, sizeof(subscribe_info_s));
164                 if (NULL == info) {
165                         CTS_ERR("calloc() Failed");
166                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
167                         return CONTACTS_ERROR_OUT_OF_MEMORY;
168                 }
169
170                 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, (char*)view_uri,
171                                         __ctsvc_db_subscriber_callback, (void*)info) != 0) {
172                         CTS_ERR("pims_ipc_subscribe error\n");
173                         free(info);
174                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
175                         return CONTACTS_ERROR_IPC;
176                 }
177                 info->view_uri = strdup(view_uri);
178                 __db_change_subscribe_list = g_slist_append(__db_change_subscribe_list, info);
179         }
180         else {
181                 GSList *l;
182                 for (l = info->callbacks;l;l=l->next) {
183                         db_callback_info_s *cb_info = l->data;
184                         if (cb_info->cb == cb && cb_info->user_data == user_data) {
185                                 CTS_ERR("The same callback(%s) is already exist", view_uri);
186                                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
187                                 return CONTACTS_ERROR_INVALID_PARAMETER;
188                         }
189                 }
190         }
191
192         cb_info = calloc(1, sizeof(db_callback_info_s));
193         cb_info->user_data = user_data;
194         cb_info->cb = cb;
195         info->callbacks = g_slist_append(info->callbacks, cb_info);
196
197         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
198         return CONTACTS_ERROR_NONE;
199 }
200
201 API int contacts_db_remove_changed_cb_with_info(const char* view_uri,
202                 contacts_db_change_cb_with_info cb, void* user_data)
203 {
204         GSList *it = NULL;
205         subscribe_info_s *info = NULL;
206
207         RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
208         RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
209
210         if (strcmp(view_uri, CTSVC_VIEW_URI_PHONELOG) != 0 &&
211                         strcmp(view_uri, CTSVC_VIEW_URI_PERSON) != 0) {
212                 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
213                 return CONTACTS_ERROR_INVALID_PARAMETER;
214         }
215
216         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
217
218         for (it=__db_change_subscribe_list;it;it=it->next) {
219                 if (!it->data) continue;
220
221                 info = it->data;
222                 if (strcmp(info->view_uri, view_uri) == 0)
223                         break;
224                 else
225                         info = NULL;
226         }
227
228         if (info) {
229                 GSList *l;
230                 for(l = info->callbacks;l;l=l->next) {
231                         db_callback_info_s *cb_info = l->data;
232                         if (cb == cb_info->cb && user_data == cb_info->user_data) {
233                                 info->callbacks = g_slist_remove(info->callbacks, cb_info);
234                                 free(cb_info);
235                                 break;
236                         }
237                 }
238                 if (g_slist_length(info->callbacks) == 0) {
239                         pims_ipc_unsubscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri);
240                         __db_change_subscribe_list = g_slist_remove(__db_change_subscribe_list, info);
241                         free(info->view_uri);
242                         free(info);
243                 }
244         }
245
246         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
247         return CONTACTS_ERROR_NONE;
248 }