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 <dynamicbox_errno.h>
24 #include "lite-errno.h"
28 #include <sys/smack.h>
29 #include <security-server.h>
32 #include <notification.h>
33 #include <notification_internal.h>
34 #include <notification_ipc.h>
35 #include <notification_noti.h>
36 #include <notification_setting_service.h>
38 #include "service_common.h"
43 #ifndef NOTIFICATION_DEL_PACKET_UNIT
44 #define NOTIFICATION_DEL_PACKET_UNIT 10
48 Eina_List *context_list;
49 struct service_context *svc_ctx;
51 .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
52 .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
62 void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
65 void (*handler_access_error)(struct tcb *tcb, struct packet *packet);
68 static inline char *_string_get(char *string)
73 if (string[0] == '\0') {
81 * FUNCTIONS to create packets
83 static inline int _priv_id_get_from_list(int num_data, int *list, int index) {
84 if (index < num_data) {
85 return *(list + index);
91 static inline struct packet *_packet_create_with_list(int op_num, int *list, int start_index) {
95 ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
96 _priv_id_get_from_list(op_num, list, start_index),
97 _priv_id_get_from_list(op_num, list, start_index + 1),
98 _priv_id_get_from_list(op_num, list, start_index + 2),
99 _priv_id_get_from_list(op_num, list, start_index + 3),
100 _priv_id_get_from_list(op_num, list, start_index + 4),
101 _priv_id_get_from_list(op_num, list, start_index + 5),
102 _priv_id_get_from_list(op_num, list, start_index + 6),
103 _priv_id_get_from_list(op_num, list, start_index + 7),
104 _priv_id_get_from_list(op_num, list, start_index + 8),
105 _priv_id_get_from_list(op_num, list, start_index + 9)
112 static void _handler_insert_noti(struct tcb *tcb, struct packet *packet, notification_h noti, void *data)
114 int ret = 0, ret_p = 0;
116 struct packet *packet_reply = NULL;
117 struct packet *packet_service = NULL;
119 ret = notification_noti_insert(noti);
120 notification_get_id(noti, NULL, &priv_id);
121 DbgPrint("priv_id: [%d]\n", priv_id);
122 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
124 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
125 ErrPrint("failed to send reply packet: %d\n", ret_p);
127 packet_destroy(packet_reply);
129 ErrPrint("failed to create a reply packet\n");
132 if (ret != NOTIFICATION_ERROR_NONE) {
133 ErrPrint("failed to insert a notification: %d\n", ret);
137 packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
138 if (packet_service != NULL) {
139 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
140 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
142 packet_destroy(packet_service);
144 ErrPrint("failed to create a multicats packet\n");
148 /*static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data) // not used
150 notification_h noti = NULL;
152 noti = notification_create(NOTIFICATION_TYPE_NOTI);
154 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
155 _handler_insert_noti(tcb, packet, noti, data);
157 ErrPrint("Failed to create the packet");
159 notification_free(noti);
163 static void _handler_update_noti(struct tcb *tcb, struct packet *packet, notification_h noti, void *data)
165 int ret = 0, ret_p = 0;
167 struct packet *packet_reply = NULL;
168 struct packet *packet_service = NULL;
170 ret = notification_noti_update(noti);
172 notification_get_id(noti, NULL, &priv_id);
173 DbgPrint("priv_id: [%d]\n", priv_id);
174 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
176 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
177 ErrPrint("failed to send reply packet:%d\n", ret_p);
179 packet_destroy(packet_reply);
181 ErrPrint("failed to create a reply packet\n");
184 if (ret != NOTIFICATION_ERROR_NONE) {
185 ErrPrint("failed to update a notification:%d\n", ret);
189 packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
190 if (packet_service != NULL) {
191 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
192 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
194 packet_destroy(packet_service);
198 static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
200 notification_h noti = NULL;
202 noti = notification_create(NOTIFICATION_TYPE_NOTI);
204 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
205 _handler_update_noti(tcb, packet, noti, data);
207 ErrPrint("Failed to create the packet");
209 notification_free(noti);
213 static void _handler_check_noti_by_tag(struct tcb *tcb, struct packet *packet, void *data)
216 notification_h noti = NULL;
218 noti = notification_create(NOTIFICATION_TYPE_NOTI);
220 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
221 ret = notification_noti_check_tag(noti);
222 if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID) {
223 _handler_insert_noti(tcb, packet, noti, data);
224 } else if (ret == NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
225 _handler_update_noti(tcb, packet, noti, data);
228 notification_free(noti);
232 static void _handler_load_noti_by_tag(struct tcb *tcb, struct packet *packet, void *data)
234 int ret = 0, ret_p = 0;
237 struct packet *packet_reply = NULL;
238 notification_h noti = NULL;
240 noti = notification_create(NOTIFICATION_TYPE_NOTI);
242 if (packet_get(packet, "ss", &pkgname, &tag) == 2) {
243 ret = notification_noti_get_by_tag(noti, pkgname, tag);
244 packet_reply = notification_ipc_make_reply_packet_from_noti(noti, packet);
246 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
247 ErrPrint("failed to send reply packet: %d\n", ret_p);
249 packet_destroy(packet_reply);
251 ErrPrint("failed to create a reply packet\n");
254 if (ret != NOTIFICATION_ERROR_NONE) {
255 ErrPrint("failed to load_noti_by_tag : %d\n", ret);
256 notification_free(noti);
260 ErrPrint("Failed to create the packet");
262 notification_free(noti);
267 static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
270 struct packet *packet_reply = NULL;
272 packet_reply = packet_create_reply(packet, "i", ret);
274 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
275 ErrPrint("failed to send reply packet:%d\n", ret);
277 packet_destroy(packet_reply);
279 ErrPrint("failed to create a reply packet\n");
282 if ((ret = service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE)) < 0) {
283 ErrPrint("failed to send a multicast packet:%d\n", ret);
287 static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
290 int ret = 0, ret_p = 0;
292 struct packet *packet_reply = NULL;
293 struct packet *packet_service = NULL;
294 char *pkgname = NULL;
296 if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
297 pkgname = _string_get(pkgname);
299 ret = notification_noti_delete_by_priv_id_get_changes(pkgname, priv_id, &num_changes);
301 DbgPrint("priv_id: [%d] num_delete:%d\n", priv_id, num_changes);
302 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
304 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
305 ErrPrint("failed to send reply packet:%d\n", ret_p);
307 packet_destroy(packet_reply);
309 ErrPrint("failed to create a reply packet\n");
312 if (ret != NOTIFICATION_ERROR_NONE || num_changes <= 0) {
313 ErrPrint("failed to delete a notification:%d %d\n", ret, num_changes);
317 packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
318 if (packet_service != NULL) {
319 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
320 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
322 packet_destroy(packet_service);
325 ErrPrint("Failed to get data from the packet");
329 static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
331 int ret = 0, ret_p = 0;
332 struct packet *packet_reply = NULL;
333 struct packet *packet_service = NULL;
334 char *pkgname = NULL;
335 notification_type_e type = 0;
337 int *list_deleted = NULL;
339 if (packet_get(packet, "si", &pkgname, &type) == 2) {
340 pkgname = _string_get(pkgname);
341 DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
343 ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
344 DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
346 packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
348 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
349 ErrPrint("failed to send reply packet:%d\n", ret_p);
351 packet_destroy(packet_reply);
353 ErrPrint("failed to create a reply packet\n");
356 if (ret != NOTIFICATION_ERROR_NONE) {
357 ErrPrint("failed to delete notifications:%d\n", ret);
358 if (list_deleted != NULL) {
359 DbgFree(list_deleted);
364 if (num_deleted > 0) {
365 if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
366 packet_service = _packet_create_with_list(num_deleted, list_deleted, 0);
368 if (packet_service) {
369 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
370 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
372 packet_destroy(packet_service);
374 ErrPrint("failed to create a multicast packet\n");
378 int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
380 for (set = 0; set <= set_total; set++) {
381 packet_service = _packet_create_with_list(num_deleted,
382 list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
384 if (packet_service) {
385 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
386 ErrPrint("failed to send a multicast packet:%d\n", ret_p);
388 packet_destroy(packet_service);
390 ErrPrint("failed to create a multicast packet\n");
396 if (list_deleted != NULL) {
397 DbgFree(list_deleted);
401 ErrPrint("Failed to get data from the packet");
405 static void _handler_noti_property_set(struct tcb *tcb, struct packet *packet, void *data)
407 int ret = 0, ret_p = 0;
408 struct packet *packet_reply = NULL;
409 char *pkgname = NULL;
410 char *property = NULL;
413 if (packet_get(packet, "sss", &pkgname, &property, &value) == 3) {
414 pkgname = _string_get(pkgname);
415 property = _string_get(property);
416 value = _string_get(value);
418 ret = notification_setting_db_set(pkgname, property, value);
420 packet_reply = packet_create_reply(packet, "ii", ret, ret);
422 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
423 ErrPrint("failed to send reply packet:%d\n", ret_p);
425 packet_destroy(packet_reply);
427 ErrPrint("failed to create a reply packet\n");
430 if (ret != NOTIFICATION_ERROR_NONE) {
431 ErrPrint("failed to set noti property:%d\n", ret);
434 ErrPrint("Failed to get data from the packet");
438 static void _handler_noti_property_get(struct tcb *tcb, struct packet *packet, void *data)
440 int ret = 0, ret_p = 0;
441 struct packet *packet_reply = NULL;
442 char *pkgname = NULL;
443 char *property = NULL;
446 if (packet_get(packet, "sss", &pkgname, &property) == 2) {
447 pkgname = _string_get(pkgname);
448 property = _string_get(property);
450 ret = notification_setting_db_get(pkgname, property, &value);
452 packet_reply = packet_create_reply(packet, "is", ret, value);
454 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
455 ErrPrint("failed to send reply packet:%d\n", ret_p);
457 packet_destroy(packet_reply);
459 ErrPrint("failed to create a reply packet\n");
468 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
471 struct packet *packet_reply;
473 ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
475 packet_reply = packet_create_reply(packet, "i", ret);
477 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
478 ErrPrint("failed to send reply packet:%d\n", ret);
480 packet_destroy(packet_reply);
482 ErrPrint("failed to create a reply packet\n");
486 static void _handler_post_toast_message(struct tcb *tcb, struct packet *packet, void *data)
489 struct packet *packet_reply = NULL;
491 packet_reply = packet_create_reply(packet, "i", ret);
493 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
494 ErrPrint("failed to send reply packet:%d\n", ret);
496 packet_destroy(packet_reply);
498 ErrPrint("failed to create a reply packet\n");
501 if ((ret = service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE)) < 0) {
502 ErrPrint("failed to send a multicast packet:%d\n", ret);
508 * SERVICE PERMISSION CHECK
510 static void _permission_check_common(struct tcb *tcb, struct packet *packet)
513 struct packet *packet_reply = NULL;
515 packet_reply = packet_create_reply(packet, "ii", NOTIFICATION_ERROR_PERMISSION_DENIED, 0);
517 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
518 ErrPrint("Failed to send a reply packet:%d", ret_p);
520 packet_destroy(packet_reply);
522 ErrPrint("Failed to create a reply packet");
526 static void _permission_check_refresh(struct tcb *tcb, struct packet *packet)
529 struct packet *packet_reply = NULL;
531 packet_reply = packet_create_reply(packet, "i", NOTIFICATION_ERROR_PERMISSION_DENIED);
533 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
534 ErrPrint("Failed to send a reply packet:%d", ret_p);
536 packet_destroy(packet_reply);
538 ErrPrint("Failed to create a reply packet");
542 static void _permission_check_property_get(struct tcb *tcb, struct packet *packet)
545 struct packet *packet_reply = NULL;
547 packet_reply = packet_create_reply(packet, "is", NOTIFICATION_ERROR_PERMISSION_DENIED, NULL);
549 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
550 ErrPrint("Failed to send a reply packet:%d", ret_p);
552 packet_destroy(packet_reply);
554 ErrPrint("Failed to create a reply packet");
558 static int _persmission_check(int fd, struct noti_service *service)
562 if (service->rule != NULL && service->access != NULL) {
563 ret = security_server_check_privilege_by_sockfd(fd, service->rule, service->access);
564 if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
565 ErrPrint("SMACK:Access denied\n");
574 * NOTIFICATION SERVICE INITIALIZATION
576 static void _notification_data_init(void)
580 char *noti_pkgname = NULL;
581 notification_h noti = NULL;
582 notification_list_h noti_list = NULL;
583 notification_list_h noti_list_head = NULL;
584 notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
586 notification_get_list(NOTIFICATION_TYPE_NONE, -1, ¬i_list);
587 noti_list_head = noti_list;
589 while (noti_list != NULL) {
590 noti = notification_list_get_data(noti_list);
592 notification_get_id(noti, NULL, &priv_id);
593 notification_get_pkgname(noti, ¬i_pkgname);
594 notification_get_property(noti, &property);
595 notification_get_type(noti, ¬i_type);
597 if (noti_type == NOTIFICATION_TYPE_ONGOING
598 || property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
599 notification_noti_delete_by_priv_id(noti_pkgname, priv_id);
602 noti_list = notification_list_get_next(noti_list);
605 if (noti_list_head != NULL) {
606 notification_free_list(noti_list_head);
610 static void _notification_init(void) {
612 int restart_count = 0;
614 ret = vconf_get_int(VCONFKEY_MASTER_RESTART_COUNT, &restart_count);
615 if (ret == 0 && restart_count <= 1) {
616 _notification_data_init();
623 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
628 static struct noti_service service_req_table[] = {
631 .handler = _handler_check_noti_by_tag,
632 .rule = "data-provider-master::notification.client",
634 .handler_access_error = _permission_check_common,
637 .cmd = "update_noti",
638 .handler = _handler_update,
639 .rule = "data-provider-master::notification.client",
641 .handler_access_error = _permission_check_common,
644 .cmd = "load_noti_by_tag",
645 .handler = _handler_load_noti_by_tag,
646 .rule = "data-provider-master::notification.client",
648 .handler_access_error = _permission_check_common,
651 .cmd = "refresh_noti",
652 .handler = _handler_refresh,
653 .rule = "data-provider-master::notification.client",
655 .handler_access_error = _permission_check_refresh,
658 .cmd = "del_noti_single",
659 .handler = _handler_delete_single,
660 .rule = "data-provider-master::notification.client",
662 .handler_access_error = _permission_check_common,
665 .cmd = "del_noti_multiple",
666 .handler = _handler_delete_multiple,
667 .rule = "data-provider-master::notification.client",
669 .handler_access_error = _permission_check_common,
672 .cmd = "set_noti_property",
673 .handler = _handler_noti_property_set,
674 .rule = "data-provider-master::notification.client",
676 .handler_access_error = _permission_check_common,
679 .cmd = "get_noti_property",
680 .handler = _handler_noti_property_get,
681 .rule = "data-provider-master::notification.client",
683 .handler_access_error = _permission_check_property_get,
686 .cmd = "service_register",
687 .handler = _handler_service_register,
690 .handler_access_error = NULL,
694 .handler = _handler_post_toast_message,
697 .handler_access_error = NULL,
704 .handler_access_error = NULL,
709 DbgPrint("TCB: %p is terminated\n", tcb);
713 command = packet_command(packet);
715 ErrPrint("Invalid command\n");
719 switch (packet_type(packet)) {
721 /* Need to send reply packet */
722 DbgPrint("%p REQ: Command: [%s]\n", tcb, command);
724 for (i = 0; service_req_table[i].cmd; i++) {
725 if (strcmp(service_req_table[i].cmd, command)) {
729 if (_persmission_check(tcb_fd(tcb), &(service_req_table[i])) == 1) {
730 service_req_table[i].handler(tcb, packet, data);
732 if (service_req_table[i].handler_access_error != NULL) {
733 service_req_table[i].handler_access_error(tcb, packet);
740 case PACKET_REQ_NOACK:
745 ErrPrint("Packet type is not valid[%s]\n", command);
750 * return value has no meanning,
751 * it will be printed by dlogutil.
759 * Do not try to do anyother operation in these functions
761 HAPI int notification_service_init(void)
763 if (s_info.svc_ctx) {
764 ErrPrint("Already initialized\n");
765 return DBOX_STATUS_ERROR_ALREADY;
768 _notification_init();
770 s_info.svc_ctx = service_common_create(NOTIFICATION_SOCKET, service_thread_main, NULL);
771 if (!s_info.svc_ctx) {
772 ErrPrint("Unable to activate service thread\n");
773 return DBOX_STATUS_ERROR_FAULT;
776 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
777 if (errno != EOPNOTSUPP) {
778 ErrPrint("Unable to set SMACK label(%d)\n", errno);
779 service_common_destroy(s_info.svc_ctx);
780 s_info.svc_ctx = NULL;
781 return DBOX_STATUS_ERROR_FAULT;
785 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
786 if (errno != EOPNOTSUPP) {
787 ErrPrint("Unable to set SMACK label(%d)\n", errno);
788 service_common_destroy(s_info.svc_ctx);
789 s_info.svc_ctx = NULL;
790 return DBOX_STATUS_ERROR_FAULT;
794 DbgPrint("Successfully initiated\n");
795 return DBOX_STATUS_ERROR_NONE;
798 HAPI int notification_service_fini(void)
800 if (!s_info.svc_ctx) {
801 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
804 service_common_destroy(s_info.svc_ctx);
805 s_info.svc_ctx = NULL;
806 DbgPrint("Successfully Finalized\n");
807 return DBOX_STATUS_ERROR_NONE;