2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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.
29 #include <app_service.h>
30 #include <app_service_private.h>
36 #define LOG_TAG "TIZEN_N_SERVICE"
38 #define BUNDLE_KEY_PREFIX_AUL "__AUL_"
39 #define BUNDLE_KEY_PREFIX_SERVICE "__APP_SVC_"
41 #define BUNDLE_KEY_OPERATION "__APP_SVC_OP_TYPE__"
42 #define BUNDLE_KEY_URI "__APP_SVC_URI__"
43 #define BUNDLE_KEY_MIME "__APP_SVC_MIME_TYPE__"
44 #define BUNDLE_KEY_DATA "__APP_SVC_DATA__"
45 #define BUNDLE_KEY_PACKAGE "__APP_SVC_PKG_NAME__"
59 typedef struct service_request_context_s {
61 service_reply_cb reply_cb;
63 } *service_request_context_h;
65 static int service_create_reply(bundle *data, struct service_s **service);
67 static const char* service_error_to_string(service_error_e error)
71 case SERVICE_ERROR_NONE:
74 case SERVICE_ERROR_INVALID_PARAMETER:
75 return "INVALID_PARAMETER";
77 case SERVICE_ERROR_OUT_OF_MEMORY:
78 return "OUT_OF_MEMORY";
80 case SERVICE_ERROR_APP_NOT_FOUND:
81 return "APP_NOT_FOUND";
83 case SERVICE_ERROR_KEY_NOT_FOUND:
84 return "KEY_NOT_FOUND";
86 case SERVICE_ERROR_KEY_REJECTED:
87 return "KEY_REJECTED";
89 case SERVICE_ERROR_INVALID_DATA_TYPE:
90 return "INVALID_DATA_TYPE";
97 int service_error(service_error_e error, const char* function, const char *description)
101 LOGE("[%s] %s(0x%08x) : %s", function, service_error_to_string(error), error, description);
105 LOGE("[%s] %s(0x%08x)", function, service_error_to_string(error), error);
111 static int service_validate_extra_data(const char *data)
113 if (data == NULL || data[0] == '\0')
115 return SERVICE_ERROR_INVALID_PARAMETER;
118 return SERVICE_ERROR_NONE;
121 static int service_valiate_service(service_h service)
123 if (service == NULL || service->data == NULL)
125 return SERVICE_ERROR_INVALID_PARAMETER;
128 return SERVICE_ERROR_NONE;
131 static int service_new_id()
137 int service_validate_internal_key(const char *key)
139 if (strncmp(BUNDLE_KEY_PREFIX_AUL, key, strlen(BUNDLE_KEY_PREFIX_AUL)) == 0)
144 if (strncmp(BUNDLE_KEY_PREFIX_SERVICE, key, strlen(BUNDLE_KEY_PREFIX_SERVICE)) == 0)
152 static void service_request_result_broker(bundle *appsvc_bundle, int appsvc_request_code, appsvc_result_val appsvc_result, void *appsvc_data)
154 service_request_context_h request_context;
156 service_h reply = NULL;
157 service_result_e result;
159 service_reply_cb reply_cb;
161 if (appsvc_data == NULL)
163 service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid service reply");
167 if (service_create_reply(appsvc_bundle, &reply) != 0)
169 service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create service reply");
173 request_context = appsvc_data;
174 request = request_context->service;
176 switch (appsvc_result)
179 result = SERVICE_RESULT_SUCCEEDED;
182 case APPSVC_RES_NOT_OK:
183 result = SERVICE_RESULT_FAILED;
186 case APPSVC_RES_CANCEL:
187 result = SERVICE_RESULT_CANCELED;
191 result = SERVICE_RESULT_CANCELED;
195 user_data = request_context->user_data;
197 reply_cb = request_context->reply_cb;
199 if (reply_cb != NULL)
201 reply_cb(request, reply, result, user_data);
205 service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback ");
211 int service_create(service_h *service)
213 return service_create_request(NULL, service);
216 int service_create_request(bundle *data, service_h *service)
218 struct service_s *service_request;
222 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
225 service_request = malloc(sizeof(struct service_s));
227 if (service_request == NULL)
229 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle");
232 service_request->type = SERVICE_TYPE_REQUEST;
236 service_request->data = bundle_dup(data);
240 service_request->data = bundle_create();
243 if (service_request->data == NULL)
245 free(service_request);
246 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a bundle");
249 service_request->id = service_new_id();
251 *service = service_request;
253 return SERVICE_ERROR_NONE;
256 int service_create_event(bundle *data, struct service_s **service)
258 struct service_s *service_event;
260 const char *operation;
262 if (data == NULL || service == NULL)
264 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
267 service_event = malloc(sizeof(struct service_s));
269 if (service_event == NULL)
271 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle");
274 service_event->type = SERVICE_TYPE_EVENT;
275 service_event->data = bundle_dup(data);
276 service_event->id = service_new_id();
278 operation = appsvc_get_operation(service_event->data);
280 if (operation == NULL)
282 appsvc_set_operation(service_event->data, SERVICE_OPERATION_DEFAULT);
285 *service = service_event;
287 return SERVICE_ERROR_NONE;
290 int service_impl_create_event(bundle *data, struct service_s **service)
292 return service_create_event(data, service);
295 static int service_create_reply(bundle *data, struct service_s **service)
297 struct service_s *service_reply;
299 if (data == NULL || service == NULL)
301 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
304 service_reply = malloc(sizeof(struct service_s));
306 if (service_reply == NULL)
308 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle");
311 service_reply->type = SERVICE_TYPE_REPLY;
312 service_reply->data = bundle_dup(data);
313 service_reply->id = service_new_id();
315 *service = service_reply;
317 return SERVICE_ERROR_NONE;
320 int service_destroy(service_h service)
322 if (service_valiate_service(service))
324 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
327 bundle_free(service->data);
328 service->data = NULL;
331 return SERVICE_ERROR_NONE;
334 int service_to_bundle(service_h service, bundle **data)
336 if (service_valiate_service(service) || data == NULL)
338 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
341 *data = service->data;
343 return SERVICE_ERROR_NONE;
346 int service_set_operation(service_h service, const char *operation)
348 if (service_valiate_service(service))
350 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
353 if (operation != NULL)
355 if (appsvc_set_operation(service->data, operation) != 0)
357 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid operation");
362 bundle_del(service->data, BUNDLE_KEY_OPERATION);
365 return SERVICE_ERROR_NONE;
368 int service_get_operation(service_h service, char **operation)
370 const char *operation_value;
372 if (service_valiate_service(service) || operation == NULL)
374 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
377 operation_value = appsvc_get_operation(service->data);
379 if (operation_value != NULL)
381 *operation = strdup(operation_value);
388 return SERVICE_ERROR_NONE;
392 int service_set_uri(service_h service, const char *uri)
394 if (service_valiate_service(service))
396 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
401 if (appsvc_set_uri(service->data, uri) != 0)
403 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid URI");
408 bundle_del(service->data, BUNDLE_KEY_URI);
411 return SERVICE_ERROR_NONE;
415 int service_get_uri(service_h service, char **uri)
417 const char *uri_value;
419 if (service_valiate_service(service) || uri == NULL)
421 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
424 uri_value = appsvc_get_uri(service->data);
426 if (uri_value != NULL)
428 *uri = strdup(uri_value);
435 return SERVICE_ERROR_NONE;
439 int service_set_mime(service_h service, const char *mime)
441 if (service_valiate_service(service))
443 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
448 if (appsvc_set_mime(service->data, mime) != 0)
450 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid MIME type");
455 bundle_del(service->data, BUNDLE_KEY_MIME);
458 return SERVICE_ERROR_NONE;
462 int service_get_mime(service_h service, char **mime)
464 const char *mime_value;
466 if (service_valiate_service(service) || mime == NULL)
468 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
471 mime_value = appsvc_get_mime(service->data);
473 if (mime_value != NULL)
475 *mime = strdup(mime_value);
482 return SERVICE_ERROR_NONE;
486 int service_set_package(service_h service, const char *package)
488 if (service_valiate_service(service))
490 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
495 if (appsvc_set_pkgname(service->data, package) != 0)
497 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid package");
502 bundle_del(service->data, BUNDLE_KEY_PACKAGE);
505 return SERVICE_ERROR_NONE;
508 int service_get_package(service_h service, char **package)
510 const char *package_value;
512 if (service_valiate_service(service) || package == NULL)
514 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
517 package_value = appsvc_get_pkgname(service->data);
519 if (package_value != NULL)
521 *package = strdup(package_value);
528 return SERVICE_ERROR_NONE;
531 int service_clone(service_h *clone, service_h service)
533 service_h service_clone;
535 if (service_valiate_service(service) || clone == NULL)
537 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
540 service_clone = malloc(sizeof(struct service_s));
542 if (service_clone == NULL)
544 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle");
547 service_clone->id = service_new_id();
548 service_clone->type = service->type;
549 service_clone->data = bundle_dup(service->data);
551 *clone = service_clone;
553 return SERVICE_ERROR_NONE;
557 int service_send_launch_request(service_h service, service_reply_cb callback, void *user_data)
559 const char *operation;
564 bool implicit_default_operation = false;
567 service_request_context_h request_context = NULL;
569 if (service_valiate_service(service))
571 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
574 operation = appsvc_get_operation(service->data);
576 if (operation == NULL)
578 implicit_default_operation = true;
579 operation = SERVICE_OPERATION_DEFAULT;
582 uri = appsvc_get_uri(service->data);
583 mime = appsvc_get_mime(service->data);
584 package = appsvc_get_pkgname(service->data);
586 // operation : default
587 if (!strcmp(operation, SERVICE_OPERATION_DEFAULT))
591 return service_error(SERVICE_ERROR_APP_NOT_FOUND, __FUNCTION__, "package must be specified if the operation is default value");
595 if (callback != NULL)
597 request_context = calloc(1, sizeof(struct service_request_context_s));
598 // request_context will be deallocated from service_request_result_broker()
600 if (request_context == NULL)
602 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
605 request_context->reply_cb = callback;
606 request_context->service = service;
607 request_context->user_data = user_data;
610 if (implicit_default_operation == true)
612 appsvc_set_operation(service->data, SERVICE_OPERATION_DEFAULT);
615 launch_pid = appsvc_run_service(service->data, service->id, callback ? service_request_result_broker : NULL, request_context);
617 if (implicit_default_operation == true)
619 bundle_del(service->data, BUNDLE_KEY_OPERATION);
624 return service_error(SERVICE_ERROR_APP_NOT_FOUND, __FUNCTION__, NULL);
627 return SERVICE_ERROR_NONE;
630 static bool service_copy_reply_data_cb(service_h service, const char *key, void *user_data)
632 bundle *reply_data = user_data;
634 char **value_array = NULL;
635 int value_array_length = 0;
636 int value_array_index = 0;
638 if (reply_data == NULL)
640 service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
644 if (appsvc_data_is_array(service->data, key))
646 service_get_extra_data_array(service, key, &value_array, &value_array_length);
647 appsvc_add_data_array(reply_data, key, (const char**)value_array, value_array_length);
649 for (value_array_index=0; value_array_index < value_array_length; value_array_index++)
651 free(value_array[value_array_index]);
658 service_get_extra_data(service, key, &value);
659 appsvc_add_data(reply_data, key, value);
666 int service_reply_to_launch_request(service_h reply, service_h request, service_result_e result)
671 if (service_valiate_service(reply) || service_valiate_service(request))
673 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
676 if (appsvc_create_result_bundle(request->data, &reply_data) != 0)
678 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a result bundle");
681 service_foreach_extra_data(reply, service_copy_reply_data_cb, reply_data);
685 case SERVICE_RESULT_SUCCEEDED:
686 appsvc_result = APPSVC_RES_OK;
689 case SERVICE_RESULT_FAILED:
690 appsvc_result = APPSVC_RES_NOT_OK;
693 case SERVICE_RESULT_CANCELED:
694 appsvc_result = APPSVC_RES_CANCEL;
698 appsvc_result = APPSVC_RES_CANCEL;
702 appsvc_send_result(reply_data, appsvc_result);
704 return SERVICE_ERROR_NONE;
708 int service_add_extra_data(service_h service, const char *key, const char *value)
710 if (service_valiate_service(service) || service_validate_extra_data(key) || service_validate_extra_data(value))
712 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
715 if (service_validate_internal_key(key))
717 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
720 if (appsvc_get_data(service->data, key) != NULL)
722 // overwrite any existing value
723 bundle_del(service->data, key);
726 if (appsvc_add_data(service->data, key, value) != 0)
728 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add data to the appsvc handle");
731 return SERVICE_ERROR_NONE;
735 int service_add_extra_data_array(service_h service, const char *key, const char* value[], int length)
737 if (service_valiate_service(service) || service_validate_extra_data(key))
739 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
742 if (value == NULL || length <= 0)
744 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid array");
747 if (service_validate_internal_key(key))
749 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
752 if (appsvc_get_data_array(service->data, key, NULL) != NULL)
754 // overwrite any existing value
755 bundle_del(service->data,key);
758 if (appsvc_add_data_array(service->data, key, value, length) != 0)
760 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add array data to the appsvc handle");
763 return SERVICE_ERROR_NONE;
767 int service_remove_extra_data(service_h service, const char *key)
769 if (service_valiate_service(service) || service_validate_extra_data(key))
771 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
774 if (service_validate_internal_key(key))
776 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
779 if (bundle_del(service->data, key))
781 return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
784 return SERVICE_ERROR_NONE;
788 int service_get_extra_data(service_h service, const char *key, char **value)
790 const char *data_value;
792 if (service_valiate_service(service) || service_validate_extra_data(key) || value == NULL)
794 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
798 if (service_validate_internal_key(key))
800 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
803 data_value = appsvc_get_data(service->data, key);
805 if (data_value == NULL)
807 if (errno == ENOTSUP)
809 return service_error(SERVICE_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL);
813 return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
817 *value = strdup(data_value);
819 return SERVICE_ERROR_NONE;
823 int service_get_extra_data_array(service_h service, const char *key, char ***value, int *length)
825 const char **array_data;
826 int array_data_length;
827 char **array_data_clone;
830 if (service_valiate_service(service) || service_validate_extra_data(key))
832 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
835 if (value == NULL || length == 0)
837 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
840 if (service_validate_internal_key(key))
842 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
845 array_data = appsvc_get_data_array(service->data, key, &array_data_length);
847 if (array_data == NULL)
849 if (errno == ENOTSUP)
851 return service_error(SERVICE_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL);
855 return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL);
859 array_data_clone = calloc(array_data_length, sizeof(char*));
861 if (array_data_clone == NULL)
863 return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
866 for (i=0; i<array_data_length; i++)
868 if (array_data[i] != NULL)
870 array_data_clone[i] = strdup(array_data[i]);
874 *value = array_data_clone;
875 *length = array_data_length;
877 return SERVICE_ERROR_NONE;
881 int service_is_extra_data_array(service_h service, const char *key, bool *array)
883 if (service_valiate_service(service) || service_validate_extra_data(key) || array == NULL)
885 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
888 if (service_validate_internal_key(key))
890 return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use");
893 if (!appsvc_data_is_array(service->data, key))
902 return SERVICE_ERROR_NONE;
908 service_extra_data_cb callback;
911 } foreach_context_extra_data_t;
913 static void service_cb_broker_bundle_iterator(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
915 foreach_context_extra_data_t* foreach_context = NULL;
916 service_extra_data_cb extra_data_cb;
918 if (key == NULL || !(type == BUNDLE_TYPE_STR || type == BUNDLE_TYPE_STR_ARRAY))
923 foreach_context = (foreach_context_extra_data_t*)user_data;
925 if (foreach_context->foreach_break == true)
930 if (service_validate_internal_key(key))
935 extra_data_cb = foreach_context->callback;
937 if (extra_data_cb != NULL)
939 bool stop_foreach = false;
941 stop_foreach = !extra_data_cb(foreach_context->service, key, foreach_context->user_data);
943 foreach_context->foreach_break = stop_foreach;
949 int service_foreach_extra_data(service_h service, service_extra_data_cb callback, void *user_data)
951 foreach_context_extra_data_t foreach_context = {
953 .callback = callback,
954 .user_data = user_data,
955 .foreach_break = false
958 if (service_valiate_service(service) || callback == NULL)
960 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
963 bundle_foreach(service->data, service_cb_broker_bundle_iterator, &foreach_context);
965 return SERVICE_ERROR_NONE;
970 service_app_matched_cb callback;
973 } foreach_context_launchable_app_t;
975 int service_cb_broker_foreach_app_matched(const char *package, void *data)
977 foreach_context_launchable_app_t *foreach_context;
978 service_app_matched_cb app_matched_cb;
980 if (package == NULL || data == NULL)
982 service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
986 foreach_context = (foreach_context_launchable_app_t*)data;
988 if (foreach_context->foreach_break == true)
993 app_matched_cb = foreach_context->callback;
995 if (app_matched_cb != NULL)
997 bool stop_foreach = false;
999 stop_foreach = !app_matched_cb(foreach_context->service, package, foreach_context->user_data);
1001 foreach_context->foreach_break = stop_foreach;
1007 int service_foreach_app_matched(service_h service, service_app_matched_cb callback, void *user_data)
1009 foreach_context_launchable_app_t foreach_context = {
1011 .callback = callback,
1012 .user_data = user_data,
1013 .foreach_break = false
1016 if (service_valiate_service(service) || callback == NULL)
1018 return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
1021 appsvc_get_list(service->data, service_cb_broker_foreach_app_matched, &foreach_context);
1023 return SERVICE_ERROR_NONE;