Add user space access control
[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
29 typedef struct
30 {
31         contacts_db_change_cb_with_info cb;
32         void *user_data;
33 }db_callback_info_s;
34
35 typedef struct
36 {
37         char *view_uri;
38         GSList *callbacks;
39 }subscribe_info_s;
40
41 static int __ipc_pubsub_ref = 0;
42 static pims_ipc_h __ipc = NULL;
43 static GSList *__db_change_subscribe_list = NULL;
44
45 static void __ctsvc_db_subscriber_callback(pims_ipc_h ipc, pims_ipc_data_h data, void *user_data)
46 {
47         unsigned int size = 0;
48         char *str = NULL;
49         subscribe_info_s *info = user_data;
50
51         if (data)
52                 str = (char*)pims_ipc_data_get(data, &size);
53
54         if (!str) {
55                 CTS_ERR("There is no changed data");
56                 return;
57         }
58
59         if (info) {
60                 GSList *l;
61                 for (l = info->callbacks;l;l=l->next) {
62                         db_callback_info_s *cb_info = l->data;
63                         cb_info->cb(info->view_uri, str, cb_info->user_data);
64                 }
65         }
66 }
67
68 // This API should be called in CTS_MUTEX_PIMS_IPC_PUBSUB mutex
69 pims_ipc_h ctsvc_ipc_get_handle_for_change_subsciption()
70 {
71         return __ipc;
72 }
73
74 int ctsvc_ipc_create_for_change_subscription()
75 {
76         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
77
78         if (0 < __ipc_pubsub_ref) {
79                 __ipc_pubsub_ref++;
80                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
81                 return CONTACTS_ERROR_NONE;
82         }
83
84         if (!__ipc) {
85                 __ipc = pims_ipc_create_for_subscribe(CTSVC_IPC_SOCKET_PATH_FOR_CHANGE_SUBSCRIPTION);
86                 if (!__ipc) {
87                         CTS_ERR("pims_ipc_create_for_subscribe error\n");
88                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
89                         return CONTACTS_ERROR_IPC;
90                 }
91         }
92         __ipc_pubsub_ref++;
93         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
94         return CONTACTS_ERROR_NONE;
95 }
96
97 int ctsvc_ipc_destroy_for_change_subscription()
98 {
99         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
100
101         if (1 == __ipc_pubsub_ref) {
102                 pims_ipc_destroy_for_subscribe(__ipc);
103                 __ipc = NULL;
104         }
105         else if (1 < __ipc_pubsub_ref) {
106                 CTS_DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref);
107         }
108         else {
109                 CTS_DBG("System : please call connection APIs, connection count is (%d)", __ipc_pubsub_ref);
110                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
111                 return CONTACTS_ERROR_INVALID_PARAMETER;
112         }
113
114         __ipc_pubsub_ref--;
115
116         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
117         return CONTACTS_ERROR_NONE;
118 }
119
120 API int contacts_db_add_changed_cb_with_info(const char* view_uri,
121                 contacts_db_change_cb_with_info cb, void* user_data)
122 {
123         GSList *it = NULL;
124         subscribe_info_s *info = NULL;
125         db_callback_info_s *cb_info;
126
127         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
128
129         for (it=__db_change_subscribe_list;it;it=it->next) {
130                 if (!it->data) continue;
131
132                 info = it->data;
133                 if (strcmp(info->view_uri, view_uri) == 0)
134                         break;
135                 else
136                         info = NULL;
137         }
138
139         if (!info) {
140                 info = calloc(1, sizeof(subscribe_info_s));
141                 if (NULL == info) {
142                         CTS_ERR("calloc() Failed");
143                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
144                         return CONTACTS_ERROR_OUT_OF_MEMORY;
145                 }
146
147                 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, (char*)view_uri,
148                                         __ctsvc_db_subscriber_callback, (void*)info) != 0) {
149                         CTS_ERR("pims_ipc_subscribe error\n");
150                         free(info);
151                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
152                         return CONTACTS_ERROR_IPC;
153                 }
154                 info->view_uri = strdup(view_uri);
155                 __db_change_subscribe_list = g_slist_append(__db_change_subscribe_list, info);
156         }
157         else {
158                 GSList *l;
159                 for (l = info->callbacks;l;l=l->next) {
160                         db_callback_info_s *cb_info = l->data;
161                         if (cb_info->cb == cb && cb_info->user_data == user_data) {
162                                 CTS_ERR("The same callback(%s) is already exist", view_uri);
163                                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
164                                 return CONTACTS_ERROR_INVALID_PARAMETER;
165                         }
166                 }
167         }
168
169         cb_info = calloc(1, sizeof(db_callback_info_s));
170         cb_info->user_data = user_data;
171         cb_info->cb = cb;
172         info->callbacks = g_slist_append(info->callbacks, cb_info);
173
174         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
175         return CONTACTS_ERROR_NONE;
176 }
177
178 API int contacts_db_remove_changed_cb_with_info(const char* view_uri,
179                 contacts_db_change_cb_with_info cb, void* user_data)
180 {
181         GSList *it = NULL;
182         subscribe_info_s *info = NULL;
183
184         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
185
186         for (it=__db_change_subscribe_list;it;it=it->next) {
187                 if (!it->data) continue;
188
189                 info = it->data;
190                 if (strcmp(info->view_uri, view_uri) == 0)
191                         break;
192                 else
193                         info = NULL;
194         }
195
196         if (info) {
197                 GSList *l;
198                 for(l = info->callbacks;l;l=l->next) {
199                         db_callback_info_s *cb_info = l->data;
200                         if (cb == cb_info->cb && user_data == cb_info->user_data) {
201                                 info->callbacks = g_slist_remove(info->callbacks, cb_info);
202                                 break;
203                         }
204                 }
205                 if (g_slist_length(info->callbacks) == 0) {
206                         pims_ipc_unsubscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri);
207                         __db_change_subscribe_list = g_slist_remove(__db_change_subscribe_list, info);
208                         free(info->view_uri);
209                         free(info);
210                 }
211         }
212
213         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
214         return CONTACTS_ERROR_NONE;
215 }