4 * Copyright (c) 2010 - 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.
23 #include <pims-ipc-svc.h>
24 #include <pims-ipc-data.h>
27 #include "ctsvc_internal.h"
28 #include "ctsvc_ipc_define.h"
29 #include "ctsvc_ipc_marshal.h"
30 #include "ctsvc_mutex.h"
31 #include "ctsvc_client_ipc.h"
32 #include "ctsvc_client_setting.h"
33 #include "contacts_extension.h"
34 #include "ctsvc_client_utils.h"
37 contacts_db_change_cb_with_info cb;
46 static int __ipc_pubsub_ref = 0;
47 static pims_ipc_h __ipc = NULL;
48 static GSList *__db_change_subscribe_list = NULL;
50 static void _cnoti_subscribe_cb(pims_ipc_h ipc, pims_ipc_data_h data,
55 subscribe_info_s *info = user_data;
58 ret = ctsvc_ipc_unmarshal_string(data, &str);
59 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_ipc_unmarshal_string() Fail(%d)", ret);
64 ERR("There is no changed data");
72 for (l = info->callbacks; l; l = l->next) {
73 db_callback_info_s *cb_info = l->data;
75 cb_info->cb(info->view_uri, str, cb_info->user_data);
82 int _cnoti_recover_for_change_subscription()
85 subscribe_info_s *info = NULL;
87 for (it = __db_change_subscribe_list; it; it = it->next) {
93 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri,
94 _cnoti_subscribe_cb, (void*)info) != 0) {
95 ERR("pims_ipc_subscribe() Fail");
96 return CONTACTS_ERROR_IPC;
101 return CONTACTS_ERROR_NONE;
106 /* This API should be called in CTS_MUTEX_PIMS_IPC_PUBSUB mutex */
107 pims_ipc_h ctsvc_ipc_get_handle_for_change_subsciption()
112 int ctsvc_ipc_create_for_change_subscription()
114 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
116 if (0 < __ipc_pubsub_ref) {
118 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
119 return CONTACTS_ERROR_NONE;
123 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
124 uid_t uid = getuid();
126 if (ctsvc_client_is_in_system_session()) {
127 if (CONTACTS_ERROR_NONE != ctsvc_client_get_active_uid(&uid))
128 return CONTACTS_ERROR_SYSTEM;
131 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s_for_subscribe",
132 uid, CTSVC_IPC_SERVICE);
133 __ipc = pims_ipc_create_for_subscribe(sock_file);
135 /* LCOV_EXCL_START */
136 ERR("pims_ipc_create_for_subscribe() Fail");
137 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
138 return CONTACTS_ERROR_IPC;
143 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
144 return CONTACTS_ERROR_NONE;
147 /* LCOV_EXCL_START */
148 int ctsvc_ipc_recover_for_change_subscription()
151 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
152 if (__ipc_pubsub_ref <= 0) {
153 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
154 return CONTACTS_ERROR_NONE;
157 pims_ipc_destroy_for_subscribe(__ipc);
158 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
159 uid_t uid = getuid();
161 if (ctsvc_client_is_in_system_session()) {
162 if (CONTACTS_ERROR_NONE != ctsvc_client_get_active_uid(&uid))
163 return CONTACTS_ERROR_SYSTEM;
166 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s_for_subscribe",
167 uid, CTSVC_IPC_SERVICE);
168 __ipc = pims_ipc_create_for_subscribe(sock_file);
170 ERR("pims_ipc_create_for_subscribe() Fail");
171 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
172 return CONTACTS_ERROR_IPC;
174 ret = ctsvc_setting_recover_for_change_subscription();
175 if (CONTACTS_ERROR_NONE != ret) {
176 ERR("ctsvc_setting_recover_for_change_subscription() Fail(%d)", ret);
177 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
180 ret = _cnoti_recover_for_change_subscription();
181 if (CONTACTS_ERROR_NONE != ret) {
182 ERR("__ctsvc_db_recover_changed_cb_with_info() Fail(%d)", ret);
183 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
187 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
188 return CONTACTS_ERROR_NONE;
192 int ctsvc_ipc_destroy_for_change_subscription(bool is_disconnect)
194 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
196 if (0 < __ipc_pubsub_ref) {
197 pims_ipc_destroy_for_subscribe(__ipc);
199 __ipc_pubsub_ref = 0;
201 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
202 return CONTACTS_ERROR_NONE;
205 if (1 == __ipc_pubsub_ref) {
206 pims_ipc_destroy_for_subscribe(__ipc);
208 } else if (1 < __ipc_pubsub_ref) {
209 DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref);
211 /* LCOV_EXCL_START */
212 DBG("System : please call connection APIs, connection count is (%d)",
214 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
215 return CONTACTS_ERROR_INVALID_PARAMETER;
221 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
222 return CONTACTS_ERROR_NONE;
225 EXPORT_API int contacts_db_add_changed_cb_with_info(const char *view_uri,
226 contacts_db_change_cb_with_info cb, void *user_data)
228 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
230 subscribe_info_s *info = NULL;
231 db_callback_info_s *cb_info;
235 RETV_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
236 RETV_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
238 if (STRING_EQUAL == strncmp(view_uri, CTSVC_VIEW_URI_PHONELOG, strlen(CTSVC_VIEW_URI_PHONELOG))) {
239 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_PHONELOG_READ, &result);
240 if (CONTACTS_ERROR_NONE != ret) {
241 /* LCOV_EXCL_START */
242 ERR("ctsvc_ipc_client_check_permission() Fail(%d)", ret);
247 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED,
248 "Permission denied (phonelog read)");
249 } else if (STRING_EQUAL == strncmp(view_uri, CTSVC_VIEW_URI_PERSON, strlen(CTSVC_VIEW_URI_PERSON))) {
250 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
251 if (CONTACTS_ERROR_NONE != ret) {
252 /* LCOV_EXCL_START */
253 ERR("ctsvc_ipc_client_check_permission() Fail(%d)", ret);
258 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED,
259 "Permission denied (contact read)");
261 /* LCOV_EXCL_START */
262 ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON,
263 CTSVC_VIEW_URI_PHONELOG);
264 return CONTACTS_ERROR_INVALID_PARAMETER;
268 ret = ctsvc_ipc_create_for_change_subscription();
269 if (CONTACTS_ERROR_NONE != ret) {
270 /* LCOV_EXCL_START */
271 ERR("ctsvc_ipc_create_for_change_subscription() Fail(%d)", ret);
276 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
278 for (it = __db_change_subscribe_list; it; it = it->next) {
279 if (NULL == it->data) continue;
282 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
289 info = calloc(1, sizeof(subscribe_info_s));
291 /* LCOV_EXCL_START */
292 ERR("calloc() Fail");
293 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
294 return CONTACTS_ERROR_OUT_OF_MEMORY;
298 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, (char*)view_uri,
299 _cnoti_subscribe_cb, (void*)info) != 0) {
300 /* LCOV_EXCL_START */
301 ERR("pims_ipc_subscribe() Fail");
303 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
304 return CONTACTS_ERROR_IPC;
307 info->view_uri = strdup(view_uri);
308 __db_change_subscribe_list = g_slist_append(__db_change_subscribe_list, info);
311 for (l = info->callbacks; l; l = l->next) {
312 db_callback_info_s *cb_info = l->data;
313 if (cb_info->cb == cb && cb_info->user_data == user_data) {
314 /* LCOV_EXCL_START */
315 ERR("The same callback(%s) is already exist", view_uri);
316 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
317 return CONTACTS_ERROR_INVALID_PARAMETER;
323 cb_info = calloc(1, sizeof(db_callback_info_s));
324 if (NULL == cb_info) {
325 /* LCOV_EXCL_START */
326 ERR("calloc() Fail");
327 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
328 return CONTACTS_ERROR_OUT_OF_MEMORY;
331 cb_info->user_data = user_data;
333 info->callbacks = g_slist_append(info->callbacks, cb_info);
335 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
336 return CONTACTS_ERROR_NONE;
339 EXPORT_API int contacts_db_remove_changed_cb_with_info(const char *view_uri,
340 contacts_db_change_cb_with_info cb, void *user_data)
342 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
345 subscribe_info_s *info = NULL;
347 RETV_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
348 RETV_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
350 if (STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PHONELOG)
351 && STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PERSON)) {
352 /* LCOV_EXCL_START */
353 ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON,
354 CTSVC_VIEW_URI_PHONELOG);
355 return CONTACTS_ERROR_INVALID_PARAMETER;
359 ret = ctsvc_ipc_destroy_for_change_subscription(false);
360 if (CONTACTS_ERROR_NONE != ret) {
361 /* LCOV_EXCL_START */
362 ERR("ctsvc_ipc_destroy_for_change_subscription() Fail(%d)", ret);
367 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
369 for (it = __db_change_subscribe_list; it; it = it->next) {
370 if (NULL == it->data)
374 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
382 for (l = info->callbacks; l; l = l->next) {
383 db_callback_info_s *cb_info = l->data;
384 if (cb == cb_info->cb && user_data == cb_info->user_data) {
385 info->callbacks = g_slist_remove(info->callbacks, cb_info);
390 if (g_slist_length(info->callbacks) == 0) {
391 pims_ipc_unsubscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri);
392 __db_change_subscribe_list = g_slist_remove(__db_change_subscribe_list, info);
393 free(info->view_uri);
398 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
399 return CONTACTS_ERROR_NONE;