2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #if defined(HAVE_LIVEBOX)
22 #include <livebox-errno.h>
24 #include "lite-errno.h"
28 #include <sys/smack.h>
29 #include <security-server.h>
32 #include <notification_ipc.h>
33 #include <notification_noti.h>
34 #include <notification_error.h>
35 #include <notification_setting_service.h>
37 #include "service_common.h"
42 #ifndef NOTIFICATION_DEL_PACKET_UNIT
43 #define NOTIFICATION_DEL_PACKET_UNIT 10
47 Eina_List *context_list;
48 struct service_context *svc_ctx;
50 .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
51 .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
61 void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
64 void (*handler_access_error)(struct tcb *tcb, struct packet *packet);
67 static inline char *_string_get(char *string)
72 if (string[0] == '\0') {
80 * FUNCTIONS to create packets
82 static inline int _priv_id_get_from_list(int num_data, int *list, int index) {
83 if (index < num_data) {
84 return *(list + index);
90 static inline struct packet *_packet_create_with_list(int op_num, int *list, int start_index) {
94 ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
95 _priv_id_get_from_list(op_num, list, start_index),
96 _priv_id_get_from_list(op_num, list, start_index + 1),
97 _priv_id_get_from_list(op_num, list, start_index + 2),
98 _priv_id_get_from_list(op_num, list, start_index + 3),
99 _priv_id_get_from_list(op_num, list, start_index + 4),
100 _priv_id_get_from_list(op_num, list, start_index + 5),
101 _priv_id_get_from_list(op_num, list, start_index + 6),
102 _priv_id_get_from_list(op_num, list, start_index + 7),
103 _priv_id_get_from_list(op_num, list, start_index + 8),
104 _priv_id_get_from_list(op_num, list, start_index + 9)
111 static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
113 int ret = 0, ret_p = 0;
115 struct packet *packet_reply = NULL;
116 struct packet *packet_service = NULL;
117 notification_h noti = NULL;
119 noti = notification_create(NOTIFICATION_TYPE_NOTI);
121 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
122 ret = notification_noti_insert(noti);
123 notification_get_id(noti, NULL, &priv_id);
124 DbgPrint("priv_id: [%d]\n", priv_id);
125 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
127 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
128 ErrPrint("failed to send reply packet: %d\n", ret_p);
130 packet_destroy(packet_reply);
132 ErrPrint("failed to create a reply packet\n");
135 if (ret != NOTIFICATION_ERROR_NONE) {
136 ErrPrint("failed to insert a notification: %d\n", ret);
137 notification_free(noti);
141 packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
142 if (packet_service != NULL) {
143 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
144 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
146 packet_destroy(packet_service);
148 ErrPrint("failed to create a multicats packet\n");
151 ErrPrint("Failed to create the packet");
153 notification_free(noti);
157 static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
159 int ret = 0, ret_p = 0;
161 struct packet *packet_reply = NULL;
162 struct packet *packet_service = NULL;
163 notification_h noti = NULL;
165 noti = notification_create(NOTIFICATION_TYPE_NOTI);
167 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
168 ret = notification_noti_update(noti);
170 notification_get_id(noti, NULL, &priv_id);
171 DbgPrint("priv_id: [%d]\n", priv_id);
172 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
174 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
175 ErrPrint("failed to send reply packet:%d\n", ret_p);
177 packet_destroy(packet_reply);
179 ErrPrint("failed to create a reply packet\n");
182 if (ret != NOTIFICATION_ERROR_NONE) {
183 ErrPrint("failed to update a notification:%d\n", ret);
184 notification_free(noti);
188 packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
189 if (packet_service != NULL) {
190 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
191 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
193 packet_destroy(packet_service);
196 ErrPrint("Failed to create the packet");
198 notification_free(noti);
202 static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
205 struct packet *packet_reply = NULL;
207 packet_reply = packet_create_reply(packet, "i", ret);
209 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
210 ErrPrint("failed to send reply packet:%d\n", ret);
212 packet_destroy(packet_reply);
214 ErrPrint("failed to create a reply packet\n");
217 if ((ret = service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE)) < 0) {
218 ErrPrint("failed to send a multicast packet:%d\n", ret);
222 static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
225 int ret = 0, ret_p = 0;
227 struct packet *packet_reply = NULL;
228 struct packet *packet_service = NULL;
229 char *pkgname = NULL;
231 if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
232 pkgname = _string_get(pkgname);
234 ret = notification_noti_delete_by_priv_id_get_changes(pkgname, priv_id, &num_changes);
236 DbgPrint("priv_id: [%d] num_delete:%d\n", priv_id, num_changes);
237 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
239 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
240 ErrPrint("failed to send reply packet:%d\n", ret_p);
242 packet_destroy(packet_reply);
244 ErrPrint("failed to create a reply packet\n");
247 if (ret != NOTIFICATION_ERROR_NONE || num_changes <= 0) {
248 ErrPrint("failed to delete a notification:%d %d\n", ret, num_changes);
252 packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
253 if (packet_service != NULL) {
254 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
255 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
257 packet_destroy(packet_service);
260 ErrPrint("Failed to get data from the packet");
264 static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
266 int ret = 0, ret_p = 0;
267 struct packet *packet_reply = NULL;
268 struct packet *packet_service = NULL;
269 char *pkgname = NULL;
270 notification_type_e type = 0;
272 int *list_deleted = NULL;
274 if (packet_get(packet, "si", &pkgname, &type) == 2) {
275 pkgname = _string_get(pkgname);
276 DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
278 ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
279 DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
281 packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
283 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
284 ErrPrint("failed to send reply packet:%d\n", ret_p);
286 packet_destroy(packet_reply);
288 ErrPrint("failed to create a reply packet\n");
291 if (ret != NOTIFICATION_ERROR_NONE) {
292 ErrPrint("failed to delete notifications:%d\n", ret);
293 if (list_deleted != NULL) {
294 DbgFree(list_deleted);
299 if (num_deleted > 0) {
300 if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
301 packet_service = _packet_create_with_list(num_deleted, list_deleted, 0);
303 if (packet_service) {
304 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
305 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
307 packet_destroy(packet_service);
309 ErrPrint("failed to create a multicast packet\n");
313 int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
315 for (set = 0; set <= set_total; set++) {
316 packet_service = _packet_create_with_list(num_deleted,
317 list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
319 if (packet_service) {
320 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
321 ErrPrint("failed to send a multicast packet:%d\n", ret_p);
323 packet_destroy(packet_service);
325 ErrPrint("failed to create a multicast packet\n");
331 if (list_deleted != NULL) {
332 DbgFree(list_deleted);
336 ErrPrint("Failed to get data from the packet");
340 static void _handler_noti_property_set(struct tcb *tcb, struct packet *packet, void *data)
342 int ret = 0, ret_p = 0;
343 struct packet *packet_reply = NULL;
344 char *pkgname = NULL;
345 char *property = NULL;
348 if (packet_get(packet, "sss", &pkgname, &property, &value) == 3) {
349 pkgname = _string_get(pkgname);
350 property = _string_get(property);
351 value = _string_get(value);
353 ret = notification_setting_db_set(pkgname, property, value);
355 packet_reply = packet_create_reply(packet, "ii", ret, ret);
357 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
358 ErrPrint("failed to send reply packet:%d\n", ret_p);
360 packet_destroy(packet_reply);
362 ErrPrint("failed to create a reply packet\n");
365 if (ret != NOTIFICATION_ERROR_NONE) {
366 ErrPrint("failed to set noti property:%d\n", ret);
369 ErrPrint("Failed to get data from the packet");
373 static void _handler_noti_property_get(struct tcb *tcb, struct packet *packet, void *data)
375 int ret = 0, ret_p = 0;
376 struct packet *packet_reply = NULL;
377 char *pkgname = NULL;
378 char *property = NULL;
381 if (packet_get(packet, "sss", &pkgname, &property) == 2) {
382 pkgname = _string_get(pkgname);
383 property = _string_get(property);
385 ret = notification_setting_db_get(pkgname, property, &value);
387 packet_reply = packet_create_reply(packet, "is", ret, value);
389 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
390 ErrPrint("failed to send reply packet:%d\n", ret_p);
392 packet_destroy(packet_reply);
394 ErrPrint("failed to create a reply packet\n");
403 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
406 struct packet *packet_reply;
408 ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
410 packet_reply = packet_create_reply(packet, "i", ret);
412 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
413 ErrPrint("failed to send reply packet:%d\n", ret);
415 packet_destroy(packet_reply);
417 ErrPrint("failed to create a reply packet\n");
422 * SERVICE PERMISSION CHECK
424 static void _permission_check_common(struct tcb *tcb, struct packet *packet)
427 struct packet *packet_reply = NULL;
429 packet_reply = packet_create_reply(packet, "ii", NOTIFICATION_ERROR_PERMISSION_DENIED, 0);
431 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
432 ErrPrint("Failed to send a reply packet:%d", ret_p);
434 packet_destroy(packet_reply);
436 ErrPrint("Failed to create a reply packet");
440 static void _permission_check_refresh(struct tcb *tcb, struct packet *packet)
443 struct packet *packet_reply = NULL;
445 packet_reply = packet_create_reply(packet, "i", NOTIFICATION_ERROR_PERMISSION_DENIED);
447 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
448 ErrPrint("Failed to send a reply packet:%d", ret_p);
450 packet_destroy(packet_reply);
452 ErrPrint("Failed to create a reply packet");
456 static void _permission_check_property_get(struct tcb *tcb, struct packet *packet)
459 struct packet *packet_reply = NULL;
461 packet_reply = packet_create_reply(packet, "is", NOTIFICATION_ERROR_PERMISSION_DENIED, NULL);
463 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
464 ErrPrint("Failed to send a reply packet:%d", ret_p);
466 packet_destroy(packet_reply);
468 ErrPrint("Failed to create a reply packet");
472 static int _persmission_check(int fd, struct noti_service *service)
476 if (service->rule != NULL && service->access != NULL) {
477 ret = security_server_check_privilege_by_sockfd(fd, service->rule, service->access);
478 if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
479 ErrPrint("SMACK:Access denied\n");
488 * NOTIFICATION SERVICE INITIALIZATION
490 static void _notification_data_init(void)
494 char *noti_pkgname = NULL;
495 notification_h noti = NULL;
496 notification_list_h noti_list = NULL;
497 notification_list_h noti_list_head = NULL;
498 notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
500 notification_get_list(NOTIFICATION_TYPE_NONE, -1, ¬i_list);
501 noti_list_head = noti_list;
503 while (noti_list != NULL) {
504 noti = notification_list_get_data(noti_list);
506 notification_get_id(noti, NULL, &priv_id);
507 notification_get_pkgname(noti, ¬i_pkgname);
508 notification_get_property(noti, &property);
509 notification_get_type(noti, ¬i_type);
511 if (noti_type == NOTIFICATION_TYPE_ONGOING
512 || property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
513 notification_noti_delete_by_priv_id(noti_pkgname, priv_id);
516 noti_list = notification_list_get_next(noti_list);
519 if (noti_list_head != NULL) {
520 notification_free_list(noti_list_head);
524 static void _notification_init(void) {
526 int restart_count = 0;
528 ret = vconf_get_int(VCONFKEY_MASTER_RESTART_COUNT, &restart_count);
529 if (ret == 0 && restart_count <= 1) {
530 _notification_data_init();
537 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
541 static struct noti_service service_req_table[] = {
544 .handler = _handler_insert,
545 .rule = "data-provider-master::notification.client",
547 .handler_access_error = _permission_check_common,
550 .cmd = "update_noti",
551 .handler = _handler_update,
552 .rule = "data-provider-master::notification.client",
554 .handler_access_error = _permission_check_common,
557 .cmd = "refresh_noti",
558 .handler = _handler_refresh,
559 .rule = "data-provider-master::notification.client",
561 .handler_access_error = _permission_check_refresh,
564 .cmd = "del_noti_single",
565 .handler = _handler_delete_single,
566 .rule = "data-provider-master::notification.client",
568 .handler_access_error = _permission_check_common,
571 .cmd = "del_noti_multiple",
572 .handler = _handler_delete_multiple,
573 .rule = "data-provider-master::notification.client",
575 .handler_access_error = _permission_check_common,
578 .cmd = "set_noti_property",
579 .handler = _handler_noti_property_set,
580 .rule = "data-provider-master::notification.client",
582 .handler_access_error = _permission_check_common,
585 .cmd = "get_noti_property",
586 .handler = _handler_noti_property_get,
587 .rule = "data-provider-master::notification.client",
589 .handler_access_error = _permission_check_property_get,
592 .cmd = "service_register",
593 .handler = _handler_service_register,
596 .handler_access_error = NULL,
603 .handler_access_error = NULL,
608 DbgPrint("TCB: %p is terminated\n", tcb);
612 command = packet_command(packet);
614 ErrPrint("Invalid command\n");
618 switch (packet_type(packet)) {
620 /* Need to send reply packet */
621 DbgPrint("%p REQ: Command: [%s]\n", tcb, command);
623 for (i = 0; service_req_table[i].cmd; i++) {
624 if (strcmp(service_req_table[i].cmd, command)) {
628 if (_persmission_check(tcb_fd(tcb), &(service_req_table[i])) == 1) {
629 service_req_table[i].handler(tcb, packet, data);
631 if (service_req_table[i].handler_access_error != NULL) {
632 service_req_table[i].handler_access_error(tcb, packet);
639 case PACKET_REQ_NOACK:
644 ErrPrint("Packet type is not valid[%s]\n", command);
649 * return value has no meanning,
650 * it will be printed by dlogutil.
658 * Do not try to do anyother operation in these functions
660 HAPI int notification_service_init(void)
662 if (s_info.svc_ctx) {
663 ErrPrint("Already initialized\n");
664 return LB_STATUS_ERROR_ALREADY;
667 _notification_init();
669 s_info.svc_ctx = service_common_create(NOTIFICATION_SOCKET, service_thread_main, NULL);
670 if (!s_info.svc_ctx) {
671 ErrPrint("Unable to activate service thread\n");
672 return LB_STATUS_ERROR_FAULT;
675 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
676 if (errno != EOPNOTSUPP) {
677 ErrPrint("Unable to set SMACK label(%d)\n", errno);
678 service_common_destroy(s_info.svc_ctx);
679 s_info.svc_ctx = NULL;
680 return LB_STATUS_ERROR_FAULT;
684 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
685 if (errno != EOPNOTSUPP) {
686 ErrPrint("Unable to set SMACK label(%d)\n", errno);
687 service_common_destroy(s_info.svc_ctx);
688 s_info.svc_ctx = NULL;
689 return LB_STATUS_ERROR_FAULT;
693 DbgPrint("Successfully initiated\n");
694 return LB_STATUS_SUCCESS;
697 HAPI int notification_service_fini(void)
699 if (!s_info.svc_ctx) {
700 return LB_STATUS_ERROR_INVALID;
703 service_common_destroy(s_info.svc_ctx);
704 s_info.svc_ctx = NULL;
705 DbgPrint("Successfully Finalized\n");
706 return LB_STATUS_SUCCESS;