From 6c1fe3518c108484754d331b0f5e7f7a884183ab Mon Sep 17 00:00:00 2001 From: HyungKyu Song Date: Sat, 16 Feb 2013 00:11:30 +0900 Subject: [PATCH] Tizen 2.0 Release --- CMakeLists.txt | 52 +++ LICENSE | 204 +++++++++ debian/changelog | 6 + debian/compat | 1 + debian/control | 29 ++ debian/dirs | 2 + debian/libslp-shortcut-0.install.in | 1 + debian/libslp-shortcut-dev.install.in | 3 + debian/rules | 114 +++++ include/SLP_shortcut_PG.h | 58 +++ include/secom_socket.h | 50 +++ include/shortcut.h | 223 ++++++++++ libshortcut.manifest | 5 + packaging/libshortcut.spec | 52 +++ shortcut.pc.in | 11 + src/main.c | 791 ++++++++++++++++++++++++++++++++++ src/secom_socket.c | 245 +++++++++++ test/Makefile | 3 + test/application.c | 53 +++ test/homescreen.c | 40 ++ 20 files changed, 1943 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/dirs create mode 100644 debian/libslp-shortcut-0.install.in create mode 100644 debian/libslp-shortcut-dev.install.in create mode 100755 debian/rules create mode 100644 include/SLP_shortcut_PG.h create mode 100644 include/secom_socket.h create mode 100644 include/shortcut.h create mode 100644 libshortcut.manifest create mode 100644 packaging/libshortcut.spec create mode 100644 shortcut.pc.in create mode 100644 src/main.c create mode 100644 src/secom_socket.c create mode 100644 test/Makefile create mode 100644 test/application.c create mode 100644 test/homescreen.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c2e1079 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,52 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(shortcut C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${exec_prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}") +SET(VERSION_MAJOR 0) +SET(VERSION "${VERSION_MAJOR}.0.1") + +set(CMAKE_SKIP_BUILD_RPATH true) + +SET(SRCS src/main.c src/secom_socket.c) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(glib_pkg REQUIRED gobject-2.0) +pkg_check_modules(pkgs REQUIRED + glib-2.0 + dlog +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +#ADD_DEFINITIONS("-Werror") +#ADD_DEFINITIONS("-Wall") +#ADD_DEFINITIONS("-Wextra") +#ADD_DEFINITIONS("-ansi") +#ADD_DEFINITIONS("-pedantic") + +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +ADD_DEFINITIONS("-DLOG_TAG=\"${PROJECT_NAME}\"") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc") + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/shortcut.h DESTINATION include/${PROJECT_NAME}) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/SLP_shortcut_PG.h DESTINATION include/${PROJECT_NAME}) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c13a9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..0bfc7b0 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +libslp-shortcut (0.0.5) unstable; urgency=low + + * Git:165.213.180.234:/slp/pkgs/s/shortcut + * Tag: libslp-shortcut_0.0.5 + + -- Sung-jae Park Mon, 02 Jan 2012 13:15:52 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..f8a7fda --- /dev/null +++ b/debian/control @@ -0,0 +1,29 @@ +Source: libslp-shortcut +Section: libs +Priority: optional +Maintainer: Sung-jae Park , Young-joo Park +Build-Depends: debhelper (>= 5), libglib2.0-dev, dlog-dev +Standards-Version: 3.7.2 + +Package: libslp-shortcut-0 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libglib2.0-0, libdlog-0 +Description: Shortcut service supporting library (shared object) + +Package: libslp-shortcut-dev +Section: libs +Architecture: any +Depends: libslp-shortcut-0 (= ${Source-Version}) +Description: Shortcut (Add to home) service supporting library (development) +XB-Generate-Docs: yes + +Package: libslp-shortcut-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libslp-shortcut-0 (= ${Source-Version}) +Description: Shortcut service supporting library (unstripped) + + + + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/libslp-shortcut-0.install.in b/debian/libslp-shortcut-0.install.in new file mode 100644 index 0000000..a7c24c5 --- /dev/null +++ b/debian/libslp-shortcut-0.install.in @@ -0,0 +1 @@ +@PREFIX@/lib/*.so.* diff --git a/debian/libslp-shortcut-dev.install.in b/debian/libslp-shortcut-dev.install.in new file mode 100644 index 0000000..4430783 --- /dev/null +++ b/debian/libslp-shortcut-dev.install.in @@ -0,0 +1,3 @@ +@PREFIX@/include/shortcut/shortcut.h +@PREFIX@/include/shortcut/SLP_shortcut_PG.h +@PREFIX@/lib/pkgconfig/*.pc diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..6618431 --- /dev/null +++ b/debian/rules @@ -0,0 +1,114 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +BUILDDIR ?= $(CURDIR)/cmake-tmp + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + mkdir -p $(BUILDDIR) && cd $(BUILDDIR) && CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX=$(PREFIX) + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + cd $(BUILDDIR) && $(MAKE) + #docbook-to-man debian/wavplayer.sgml > wavplayer.1 + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -rm -rf $(BUILDDIR) + #rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake Makefile install_manifest.txt + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/wavplayer. + cd $(BUILDDIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot +# dh_installchangelogs +# dh_installdocs +# dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=libslp-shortcut-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/include/SLP_shortcut_PG.h b/include/SLP_shortcut_PG.h new file mode 100644 index 0000000..eec5363 --- /dev/null +++ b/include/SLP_shortcut_PG.h @@ -0,0 +1,58 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @ingroup SLP_PG + * @defgroup SHORTCUT_PG Add to home (shortcut) + * @{ + +

Introduction

+ Shortcut is a communication interfaces for homescreen and applications. To enable the add_to_home feature. Shortcut(libslp-shortcut) uses socket for IPC. + + @image html SLP_Shortcut_PG_image01.png + +

Properties

+- Types of shortcut +- Header File : shortcut.h + +

Programming Guide

+ +

Types of shortcut

+Shortcut defines 3 kinds of types. + +

1. SHORTCUT_PACKAGE

+We can use this for adding a package shortcut with additional information.
+@code +@endcode + +

2. SHORTCUT_DATA

+@code +@endcode + +

3. SHORTCUT_FILE

+@code +@endcode + +

Error code

+

1. -EINVAL

+

1. -EFAULT

+@code +@endcode +*/ + +/** +@} +*/ diff --git a/include/secom_socket.h b/include/secom_socket.h new file mode 100644 index 0000000..3e6b7d6 --- /dev/null +++ b/include/secom_socket.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +/* + * Create client connection + */ +extern int secom_create_client(const char *peer); + +/* + * Create server connection + */ +extern int secom_create_server(const char *peer); + +/* + * Get the raw handle to use it for non-blocking mode. + */ +extern int secom_get_connection_handle(int server_handle); +extern int secom_put_connection_handle(int conn_handle); + +/* + * Send data to the connected peer. + */ +extern int secom_send(int conn, const char *buffer, int size); + +/* + * Recv data from the connected peer. and its PID value + */ +extern int secom_recv(int conn, char *buffer, int size, int *sender_pid); + +/* + * Destroy a connection + */ +extern int secom_destroy(int conn); + +/* End of a file */ diff --git a/include/shortcut.h b/include/shortcut.h new file mode 100644 index 0000000..b488faf --- /dev/null +++ b/include/shortcut.h @@ -0,0 +1,223 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SHORTCUT_H__ +#define __SHORTCUT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup APPLICATION_FRAMEWORK + * @{ + */ + +/** + * @defgroup SHORTCUT Add to home (shortcut) + * @author Sung-jae Park + * @version 0.1 + * @brief To enhance the Add to home feature. Two types of API set are supported. + * One for the homescreen developers. + * The others for the application developers who should implement the Add to home feature. + */ + +/** + * @brief This function prototype is used to define a callback function for the add_to_home reqeust. + * The homescreen should define a callback as this type and implementing the service code + * for adding a new application shortcut. + * @param[in] pkgname Shortcut is added for this package. + * @param[in] name Name for created shortcut icon. + * @param[in] type 3 kinds of types are defined. + * @param[in] content_info Specific information for creating a new shortcut. + * @param[in] icon Absolute path of an icon file for this shortcut. + * @param[in] pid Process ID of who request add_to_home. + * @param[in] data Callback data. + * @return int Developer should returns the result of handling shortcut creation request. + * Returns 0, if succeed to handles the add_to_home request, or returns proper errno. + * @see shortcut_set_request_cb + * @pre None + * @post None + * @remarks None + */ +typedef int (*request_cb_t)(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, int pid, void *data); + +/** + * @brief This function prototype is used to define for receiving the result of add_to_home. + * @param[in] ret Result value, it could be 0 if succeed to add a shortcut, or errno. + * @param[in] pid Process ID of who handles this add_to_home request. + * @param[in] data Callback data. + * @return int Returns 0, if there is no error or returns errno. + * @see shortcut_add_to_home() + * @pre None + * @post None + * @remarks None + */ +typedef int (*result_cb_t)(int ret, int pid, void *data); + +/** + * @brief Basically, three types of shortcut is defined. + * Every homescreen developer should support these types of shortcut. + * Or returns proper errno to figure out why the application failed to add a shortcut. + * SHORTCUT_PACKAGE is used for adding a package itself as a shortcut + * SHORTCUT_DATA is used for adding a shortcut for "content" data. + * SHORTCUT_FILE is used for adding a shortcut for "file". + */ +enum { + SHORTCUT_PACKAGE = 0x0, /**< Launch the package using given pakcage name. */ + SHORTCUT_DATA = 0x01, /**< Launch the related package with given data(content_info). */ + SHORTCUT_FILE = 0x02, /** < Launch the related package with given filename(content_info). */ +}; + +/** + * @fn int shortcut_set_request_cb(request_cb_t request_cb, void *data) + * + * @brief Homescreen should use this function to service the shortcut creating request. + * + * @par Sync (or) Async: + * This is an asynchronous API. + * + * @par Important Notes: + * - Should be used from the homescreen. + * - Should check the return value of this function + * + * @param[in] request_cb Callback function pointer which will be invoked when add_to_home is requested. + * @param[in] data Callback data to deliver to the callback function. + * + * @return Return Type (int) + * - 0 - callback function is successfully registered + * - < 0 - Failed to register the callback function for request. + * + * @see request_cb_t + * + * @pre - You have to prepare a callback function + * + * @post - If a request is sent from the application, the registered callback will be invoked. + * + * @remarks - None + * + * @par Prospective Clients: + * Homescreen + * + * @par Example + * @code + * #include + * + * static int request_cb(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, int pid, void *data) + * { + * printf("Package name: %s\n", pkgname); + * printf("Name: %s\n", name); + * printf("Type: %d\n", type); + * printf("Content: %s\n", content_info); + * printf("Icon: %s\n", icon); + * printf("Requested from: %d\n", pid); + * printf("CBDATA: %p\n", data); + * return 0; // returns success. + * } + * + * static int app_create(void *data) + * { + * shortcut_set_request_cb(request_cb, NULL); + * return 0; + * } + * + * int main(int argc, char *argv[]) + * { + * appcore.... + * } + * + * @endcode + */ +extern int shortcut_set_request_cb(request_cb_t request_cb, void *data); + +/** + * @fn int shortcut_add_to_home(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data) + * + * @brief The application, which supporting the add_to_home feature, should invoke this. + * + * @par Sync (or) Async: + * This is an asynchronous API. + * + * @par Important Notes: + * - Application should check the return value of this function. + * - Application should check the return status from the callback function + * - Application should set the callback function to get the result of this request. + * + * @param[in] pkgname Package name of owner of this shortcut. + * @param[in] name Name for created shortcut icon. + * @param[in] type 3 kinds of types are defined. + * @param[in] content_info Specific information for delivering to the creating shortcut. + * @param[in] icon Absolute path of an icon file + * @param[in] result_cb Callback function pointer which will be invoked after add_to_home request. + * @param[in] data Callback data to deliver to the callback function. + * + * @return Return Type (int) + * - 0 - Succeed to send the request + * - <0 - Failed to send the request + * + * @see result_cb_t + * + * @pre - You have to prepare the callback function + * + * @post - You have to check the return status from callback function which is passed by argument. + * + * @remarks - If a homescreen does not support this feature, you will get proper error code. + * + * @par Prospective Clients: + * Inhouse Apps. + * + * @par Example + * @code + * + * #include + * #include + * + * static int result_cb(int ret, int pid, void *data) + * { + * if (ret < 0) + * printf("Failed to add a shortcut: %s\n", perror(ret)); + * + * printf("Processed by the %d\n", pid); + * return 0; + * } + * + * static int app_create(void *data) + * { + * shortcut_add_to_home("com.samsung.gallery", "With friends", + * SHORTCUT_DATA, "gallery:0000-0000", + * "/opt/media/Pictures/Friends.jpg", result_cb, NULL); + * return 0; + * } + * + * int main(int argc, char *argv[]) + * { + * appcore.... + * } + * + * @endcode + */ +extern int shortcut_add_to_home(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data); + +extern int add_to_home_shortcut(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data); + +#ifdef __cplusplus +} +#endif + +#endif +/* @} + * End of a file + */ diff --git a/libshortcut.manifest b/libshortcut.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/libshortcut.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/libshortcut.spec b/packaging/libshortcut.spec new file mode 100644 index 0000000..c04cf87 --- /dev/null +++ b/packaging/libshortcut.spec @@ -0,0 +1,52 @@ +Name: libshortcut +Summary: Shortcut add feature supporting library +Version: 0.0.5 +Release: 0 +Group: main/devel +License: Apache License +Source0: %{name}-%{version}.tar.gz + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +BuildRequires: cmake, gettext-tools +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) + +%description +[Shortcut] AddToHome feature supporting library for menu/home screen developers. + +%package devel +Summary: AddToHome feature supporting library development files +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +[Shortcut] AddToHome feature supporting library for menu/home screen developers +(dev). + +%prep +%setup -q + +%build +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%post + +%postun + +%files -n libshortcut +%manifest libshortcut.manifest +%defattr(-,root,root,-) +%{_libdir}/*.so* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/shortcut/SLP_shortcut_PG.h +%{_includedir}/shortcut/shortcut.h +%{_libdir}/pkgconfig/shortcut.pc diff --git a/shortcut.pc.in b/shortcut.pc.in new file mode 100644 index 0000000..9798259 --- /dev/null +++ b/shortcut.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: shortcut +Description: shortcut server platform library +Version: @VERSION@ +Requires: glib-2.0 +Libs: -L${libdir} -lshortcut +Cflags: -I${includedir} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ef4d76e --- /dev/null +++ b/src/main.c @@ -0,0 +1,791 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + + +#define EAPI __attribute__((visibility("default"))) + + + +extern int errno; + + + +struct server_cb { + request_cb_t request_cb; + void *data; +}; + + + +struct client_cb { + result_cb_t result_cb; + void *data; +}; + + + +static struct info { + pthread_mutex_t server_mutex; + int server_fd; + const char *socket_file; + struct server_cb server_cb; + unsigned int seq; +} s_info = { + .server_mutex = PTHREAD_MUTEX_INITIALIZER, + .server_fd = -1, + .socket_file = "/tmp/.shortcut", + .seq = 0, +}; + + + +struct packet { + struct { + unsigned int seq; + enum { + PACKET_ERR = 0x0, + PACKET_REQ, + PACKET_ACK, + PACKET_MAX = 0xFF, /* MAX */ + } type; + + int payload_size; + + union { + struct { + int shortcut_type; + struct { + int pkgname; + int name; + int exec; + int icon; + } field_size; + } req; + + struct { + int ret; + } ack; + } data; + } head; + + char payload[]; +}; + + + +struct connection_state { + void *data; + struct packet packet; + enum { + BEGIN, + HEADER, + PAYLOAD, + END, + ERROR, + } state; + int length; + int from_pid; + char *payload; +}; + + + +static inline +gboolean check_reply_service(int conn_fd, struct connection_state *state) +{ + struct client_cb *client_cb = state->data; + + if (client_cb->result_cb) { + /* If the callback return FAILURE, + * remove itself from the callback list */ + client_cb->result_cb(state->packet.head.data.ack.ret, + state->from_pid, client_cb->data); + } + + state->state = BEGIN; + state->length = 0; + state->from_pid = 0; + + /* NOTE: If we want close the connection, returns FALSE */ + return FALSE; +} + + + +static inline +gboolean do_reply_service(int conn_fd, struct connection_state *state) +{ + int ret; + struct packet send_packet; + + ret = -ENOSYS; + if (s_info.server_cb.request_cb) { + char *pkgname; + char *name; + char *exec; + char *icon; + + if (state->packet.head.data.req.field_size.pkgname) + pkgname = state->payload; + else + pkgname = NULL; + + if (state->packet.head.data.req.field_size.name) + name = state->payload + state->packet.head.data.req.field_size.pkgname; + else + name = NULL; + + if (state->packet.head.data.req.field_size.exec) { + exec = state->payload + state->packet.head.data.req.field_size.pkgname; + exec += state->packet.head.data.req.field_size.name; + } else { + exec = NULL; + } + + if (state->packet.head.data.req.field_size.icon) { + icon = state->payload + state->packet.head.data.req.field_size.pkgname; + icon += state->packet.head.data.req.field_size.name; + icon += state->packet.head.data.req.field_size.exec; + } else { + icon = NULL; + } + + LOGD("Pkgname: [%s] Type: [%x], Name: [%s], Exec: [%s], Icon: [%s]\n", + pkgname, + state->packet.head.data.req.shortcut_type, + name, + exec, + icon); + + ret = s_info.server_cb.request_cb( + pkgname, + name, + state->packet.head.data.req.shortcut_type, + exec, + icon, + state->from_pid, + s_info.server_cb.data); + } + + send_packet.head.type = PACKET_ACK; + send_packet.head.payload_size = 0; + send_packet.head.seq = state->packet.head.seq; + send_packet.head.data.ack.ret = ret; + + if (secom_send(conn_fd, (const char*)&send_packet, sizeof(send_packet)) != sizeof(send_packet)) { + LOGE("Faield to send ack packet\n"); + return FALSE; + } + + state->state = BEGIN; + state->length = 0; + state->from_pid = 0; + return TRUE; +} + + + +static inline +gboolean filling_payload(int conn_fd, struct connection_state *state) +{ + if (state->length < state->packet.head.payload_size) { + int ret; + int check_pid; + + ret = secom_recv(conn_fd, + state->payload + state->length, + state->packet.head.payload_size - state->length, + &check_pid); + if (ret < 0) + return FALSE; + + if (state->from_pid != check_pid) { + LOGD("PID is not matched (%d, expected %d)\n", + check_pid, state->from_pid); + return FALSE; + } + + state->length += ret; + } + + if (state->length == state->packet.head.payload_size) { + state->length = 0; + state->state = END; + } + + return TRUE; +} + + + +static inline +gboolean deal_error_packet(int conn_fd, struct connection_state *state) +{ + if (state->length < state->packet.head.payload_size) { + int ret; + char *buf; + int check_pid; + + buf = alloca(state->packet.head.payload_size - state->length); + + ret = secom_recv(conn_fd, + buf, + state->packet.head.payload_size - state->length, + &check_pid); + if (ret < 0) + return FALSE; + + if (check_pid != state->from_pid) + LOGD("PID is not matched (%d, expected %d)\n", + check_pid, state->from_pid); + + state->length += ret; + } + + if (state->length < state->packet.head.payload_size) + return TRUE; + + /* Now, drop this connection */ + return FALSE; +} + + + +static inline +gboolean filling_header(int conn_fd, struct connection_state *state) +{ + if (state->length < sizeof(state->packet)) { + int ret; + int check_pid; + + ret = secom_recv(conn_fd, + ((char*)&state->packet) + state->length, + sizeof(state->packet) - state->length, + &check_pid); + if (ret < 0) + return FALSE; + + if (state->from_pid == 0) + state->from_pid = check_pid; + + if (state->from_pid != check_pid) { + LOGD("PID is not matched (%d, expected %d)\n", + check_pid, state->from_pid); + return FALSE; + } + + state->length += ret; + } + + if (state->length < sizeof(state->packet)) + return TRUE; + + if (state->packet.head.type == PACKET_ACK) { + state->length = 0; + + if (state->packet.head.payload_size) + state->state = ERROR; + else + state->state = END; + } else if (state->packet.head.type == PACKET_REQ) { + /* Let's take the next part. */ + state->state = PAYLOAD; + state->length = 0; + + state->payload = calloc(1, state->packet.head.payload_size); + if (!state->payload) { + LOGE("Heap: %s\n", strerror(errno)); + return FALSE; + } + } else { + LOGE("Invalid packet type\n"); + return FALSE; + } + + return TRUE; +} + + + +static +gboolean client_connection_cb(GIOChannel *src, GIOCondition cond, gpointer data) +{ + int conn_fd = -1; + gboolean ret; + int read_size; + struct connection_state *state = data; + struct client_cb *client_cb = state->data; + + if (!(cond & G_IO_IN)) { + LOGE("Condition value is unexpected value\n"); + ret = FALSE; + goto out; + } + + conn_fd = g_io_channel_unix_get_fd(src); + + if (ioctl(conn_fd, FIONREAD, &read_size) < 0) { + LOGE("Failed to get q size\n"); + ret = FALSE; + goto out; + } + + if (read_size == 0) { + if (client_cb->result_cb) { + /* If the callback return FAILURE, + * remove itself from the callback list */ + client_cb->result_cb(-ECONNABORTED, + state->from_pid, client_cb->data); + } + ret = FALSE; + goto out; + } + + switch (state->state) { + case BEGIN: + state->state = HEADER; + case HEADER: + ret = filling_header(conn_fd, state); + break; + case ERROR: + ret = deal_error_packet(conn_fd, state); + break; + default: + ret = FALSE; + break; + } + + if (state->state == END) + ret = check_reply_service(conn_fd, state); + +out: + if (ret == FALSE) { + if (conn_fd >= 0) + close(conn_fd); + free(state->data); + free(state); + } + + return ret; +} + + + +static +gboolean connection_cb(GIOChannel *src, GIOCondition cond, gpointer data) +{ + int conn_fd = -1; + struct connection_state *state = data; + gboolean ret; + int read_size; + + if (!(cond & G_IO_IN)) { + ret = FALSE; + goto out; + } + + conn_fd = g_io_channel_unix_get_fd(src); + + if (ioctl(conn_fd, FIONREAD, &read_size) < 0) { + LOGE("Failed to get q size\n"); + ret = FALSE; + goto out; + } + + if (read_size == 0) { + LOGE("Disconnected\n"); + ret = FALSE; + goto out; + } + + switch (state->state) { + case BEGIN: + state->state = HEADER; + case HEADER: + ret = filling_header(conn_fd, state); + break; + case PAYLOAD: + ret = filling_payload(conn_fd, state); + break; + default: + LOGE("[%s:%d] Invalid state(%x)\n", + __func__, __LINE__, state->state); + ret = FALSE; + break; + } + + if (state->state == END) { + ret = do_reply_service(conn_fd, state); + if (state->payload) { + free(state->payload); + state->payload = NULL; + } + + memset(&state->packet, 0, sizeof(state->packet)); + } + +out: + if (ret == FALSE) { + if (conn_fd >= 0) + secom_put_connection_handle(conn_fd); + + if (state->payload) + free(state->payload); + + free(state); + } + + return ret; +} + + + +static +gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data) +{ + int server_fd; + int connection_fd; + GIOChannel *gio; + guint id; + struct connection_state *state; + + server_fd = g_io_channel_unix_get_fd(src); + if (server_fd != s_info.server_fd) { + LOGE("Unknown FD is gotten.\n"); + /* NOTE: + * In this case, don't try to do anything. + * This is not recoverble error */ + return FALSE; + } + + if (!(cond & G_IO_IN)) { + close(s_info.server_fd); + if (pthread_mutex_lock(&s_info.server_mutex) != 0) + LOGE("[%s:%d] Failed to get lock (%s)\n", + __func__, __LINE__, strerror(errno)); + s_info.server_fd = -1; + if (pthread_mutex_unlock(&s_info.server_mutex) != 0) + LOGE("[%s:%d] Failed to do unlock mutex (%s)\n", + __func__, __LINE__, strerror(errno)); + return FALSE; + } + + connection_fd = secom_get_connection_handle(server_fd); + if (connection_fd < 0) { + /* Error log will be printed from + * get_connection_handle function */ + return FALSE; + } + + if (fcntl(connection_fd, F_SETFD, FD_CLOEXEC) < 0) + LOGE("Error: %s\n", strerror(errno)); + + if (fcntl(connection_fd, F_SETFL, O_NONBLOCK) < 0) + LOGE("Error: %s\n", strerror(errno)); + + gio = g_io_channel_unix_new(connection_fd); + if (!gio) { + LOGE("Failed to create a new connection channel\n"); + secom_put_connection_handle(connection_fd); + return FALSE; + } + + state = calloc(1, sizeof(*state)); + if (!state) { + LOGE("Heap: %s\n", strerror(errno)); + secom_put_connection_handle(connection_fd); + return FALSE; + } + + state->state = BEGIN; + id = g_io_add_watch(gio, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + (GIOFunc)connection_cb, state); + if (id == 0) { + GError *err = NULL; + LOGE("Failed to create g_io watch\n"); + free(state); + g_io_channel_unref(gio); + g_io_channel_shutdown(gio, TRUE, &err); + secom_put_connection_handle(connection_fd); + return FALSE; + } + + g_io_channel_unref(gio); + return TRUE; +} + + + +static inline int init_client(struct client_cb *client_cb, + const char *packet, int packet_size) +{ + GIOChannel *gio; + guint id; + int client_fd; + struct connection_state *state; + + client_fd = secom_create_client(s_info.socket_file); + if (client_fd < 0) { + LOGE("Failed to make the client FD\n"); + return -EFAULT; + } + + if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) + LOGE("Error: %s\n", strerror(errno)); + + if (fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) + LOGE("Error: %s\n", strerror(errno)); + + gio = g_io_channel_unix_new(client_fd); + if (!gio) { + close(client_fd); + return -EFAULT; + } + + state = calloc(1, sizeof(*state)); + if (!state) { + LOGE("Error: %s\n", strerror(errno)); + close(client_fd); + return -ENOMEM; + } + + state->data = client_cb; + + id = g_io_add_watch(gio, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + (GIOFunc)client_connection_cb, state); + if (id == 0) { + GError *err = NULL; + LOGE("Failed to create g_io watch\n"); + free(state); + g_io_channel_unref(gio); + g_io_channel_shutdown(gio, TRUE, &err); + close(client_fd); + return -EFAULT; + } + + g_io_channel_unref(gio); + + if (secom_send(client_fd, packet, packet_size) != packet_size) { + GError *err = NULL; + LOGE("Failed to send all packet " + "(g_io_channel is not cleared now\n"); + free(state); + g_io_channel_shutdown(gio, TRUE, &err); + close(client_fd); + return -EFAULT; + } + + return client_fd; +} + + + +static inline +int init_server(void) +{ + GIOChannel *gio; + guint id; + + if (s_info.server_fd != -1) { + LOGE("Already initialized\n"); + return 0; + } + + if (pthread_mutex_lock(&s_info.server_mutex) != 0) { + LOGE("[%s:%d] Failed to get lock (%s)\n", + __func__, __LINE__, strerror(errno)); + return -EFAULT; + } + + unlink(s_info.socket_file); + s_info.server_fd = secom_create_server(s_info.socket_file); + + if (s_info.server_fd < 0) { + LOGE("Failed to open a socket (%s)\n", strerror(errno)); + if (pthread_mutex_unlock(&s_info.server_mutex) != 0) + LOGE("[%s:%d] Failed to do unlock mutex (%s)\n", + __func__, __LINE__, strerror(errno)); + return -EFAULT; + } + + if (fcntl(s_info.server_fd, F_SETFD, FD_CLOEXEC) < 0) + LOGE("Error: %s\n", strerror(errno)); + + if (fcntl(s_info.server_fd, F_SETFL, O_NONBLOCK) < 0) + LOGE("Error: %s\n", strerror(errno)); + + gio = g_io_channel_unix_new(s_info.server_fd); + if (!gio) { + close(s_info.server_fd); + s_info.server_fd = -1; + if (pthread_mutex_unlock(&s_info.server_mutex) != 0) + LOGE("[%s:%d] Failed to do unlock mutex (%s)\n", + __func__, __LINE__, strerror(errno)); + return -EFAULT; + } + + id = g_io_add_watch(gio, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc)accept_cb, NULL); + if (id == 0) { + GError *err = NULL; + LOGE("Failed to create g_io watch\n"); + g_io_channel_unref(gio); + g_io_channel_shutdown(gio, TRUE, &err); + close(s_info.server_fd); + s_info.server_fd = -1; + if (pthread_mutex_unlock(&s_info.server_mutex) != 0) + LOGE("[%s:%d] Failed to do unlock mutex (%s)\n", + __func__, __LINE__, strerror(errno)); + + return -EFAULT; + } + + g_io_channel_unref(gio); + + if (pthread_mutex_unlock(&s_info.server_mutex) != 0) { + GError *err = NULL; + g_io_channel_shutdown(gio, TRUE, &err); + LOGE("[%s:%d] Failed to do unlock mutex (%s)\n", + __func__, __LINE__, strerror(errno)); + /* NOTE: + * We couldn't make a lock for this statements. + * We already meet the unrecoverble error + */ + close(s_info.server_fd); + s_info.server_fd = -1; + return -EFAULT; + } + + return 0; +} + + + +EAPI int shortcut_set_request_cb(request_cb_t request_cb, void *data) +{ + int ret; + s_info.server_cb.request_cb = request_cb; + s_info.server_cb.data = data; + + ret = init_server(); + if (ret != 0) { + LOGE("Failed to initialize the server\n"); + } + + return ret; +} + + + +EAPI int add_to_home_shortcut(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data) +{ + struct packet *packet; + int pkgname_len; + int name_len; + int exec_len; + int icon_len; + int packet_size; + char *payload; + struct client_cb *client_cb; + int client_fd; + + pkgname_len = pkgname ? strlen(pkgname) + 1 : 0; + name_len = name ? strlen(name) + 1 : 0; + exec_len = content_info ? strlen(content_info) + 1 : 0; + icon_len = icon ? strlen(icon) + 1 : 0; + + packet_size = sizeof(*packet) + name_len + exec_len + icon_len + pkgname_len + 1; + + packet = alloca(packet_size); + if (!packet) { + LOGE("Heap: %s\n", strerror(errno)); + return -ENOMEM; + } + + packet->head.seq = s_info.seq++; + packet->head.type = PACKET_REQ; + packet->head.data.req.shortcut_type = type; + packet->head.data.req.field_size.pkgname = pkgname_len; + packet->head.data.req.field_size.name = name_len; + packet->head.data.req.field_size.exec = exec_len; + packet->head.data.req.field_size.icon = icon_len; + packet->head.payload_size = pkgname_len + name_len + exec_len + icon_len + 1; + + payload = packet->payload; + + if (pkgname_len) { + strncpy(payload, pkgname, pkgname_len); + payload += pkgname_len; + } + + if (name_len) { + strncpy(payload, name, name_len); + payload += name_len; + } + + if (exec_len) { + strncpy(payload, content_info, exec_len); + payload += exec_len; + } + + if (icon_len) + strncpy(payload, icon, icon_len); + + client_cb = malloc(sizeof(*client_cb)); + if (!client_cb) { + LOGE("Heap: %s\n", strerror(errno)); + return -ENOMEM; + } + + client_cb->result_cb = result_cb; + client_cb->data = data; + + if (init_client(client_cb, (const char*)packet, packet_size) < 0) { + LOGE("Failed to init client FD\n"); + free(client_cb); + return -EFAULT; + } + + return 0; +} + +EAPI int shortcut_add_to_home(const char *pkgname, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data) +{ + return add_to_home_shortcut(pkgname, name, type, content_info, icon, result_cb, data); +} + + + +/* End of a file */ diff --git a/src/secom_socket.c b/src/secom_socket.c new file mode 100644 index 0000000..60bac2b --- /dev/null +++ b/src/secom_socket.c @@ -0,0 +1,245 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +extern int errno; + + + +inline static +int create_socket(const char *peer, struct sockaddr_un *addr) +{ + int len; + int handle; + + len = sizeof(struct sockaddr_un); + bzero(addr, len); + + if (strlen(peer) >= sizeof(addr->sun_path)) { + LOGE("peer %s is too long to remember it\\n", peer); + return -1; + } + + // We can believe this has no prob, because + // we already check the size of add.rsun_path + strcpy(addr->sun_path, peer); + addr->sun_family = AF_UNIX; + + handle = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (handle < 0) { + LOGE("Failed to create a socket %s\n", strerror(errno)); + return -1; + } + + return handle; +} + + + +int secom_create_client(const char *peer) +{ + struct sockaddr_un addr; + int handle; + int state; + int on = 1; + + handle = create_socket(peer, &addr); + if (handle < 0) + return handle; + + state = connect(handle, (struct sockaddr*)&addr, sizeof(addr)); + if (state < 0) { + LOGE("Failed to connect to server [%s] %s\n", peer, strerror(errno)); + if (close(handle) < 0) + LOGE("Failed to close a handle\n"); + + return -1; + } + + if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) + LOGE("Failed to change sock opt : %s\n", strerror(errno)); + + return handle; +} + + + +int secom_create_server(const char *peer) +{ + int handle; + int state; + struct sockaddr_un addr; + + handle = create_socket(peer, &addr); + if (handle < 0) return handle; + + state = bind(handle, &addr, sizeof(addr)); + if (state < 0) { + LOGE("Failed to bind a socket %s\n", strerror(errno)); + if (close(handle) < 0) { + LOGE("Failed to close a handle\n"); + } + return -1; + } + + state = listen(handle, 5); + if (state < 0) { + LOGE("Failed to listen a socket %s\n", strerror(errno)); + if (close(handle) < 0) { + LOGE("Failed to close a handle\n"); + } + return -1; + } + + if (chmod(peer, 0666) < 0) { + LOGE("Failed to change the permission of a socket (%s)\n", strerror(errno)); + } + + return handle; +} + + + +int secom_get_connection_handle(int server_handle) +{ + struct sockaddr_un addr; + int handle; + int on = 1; + socklen_t size = sizeof(addr); + + handle = accept(server_handle, (struct sockaddr*)&addr, &size); + if (handle < 0) { + LOGE("Failed to accept a new client %s\n", strerror(errno)); + return -1; + } + + if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { + LOGE("Failed to change sock opt : %s\n", strerror(errno)); + } + + return handle; +} + + + +int secom_put_connection_handle(int conn_handle) +{ + if (close(conn_handle) < 0) { + LOGE("Failed to close a handle\n"); + return -1; + } + return 0; +} + + + +int secom_send(int handle, const char *buffer, int size) +{ + struct msghdr msg; + struct iovec iov; + int ret; + + memset(&msg, 0, sizeof(msg)); + iov.iov_base = (char*)buffer; + iov.iov_len = size; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + ret = sendmsg(handle, &msg, 0); + if (ret < 0) { + LOGE("Failed to send message [%s]\n", strerror(errno)); + return -1; + } + LOGD("Send done: %d\n", ret); + + return iov.iov_len; +} + + + +int secom_recv(int handle, char *buffer, int size, int *sender_pid) +{ + struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec iov; + int _pid; + int ret; + char control[1024]; + + if (!sender_pid) sender_pid = &_pid; + *sender_pid = -1; + + memset(&msg, 0, sizeof(msg)); + iov.iov_base = buffer; + iov.iov_len = size; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + ret = recvmsg(handle, &msg, 0); + if (ret < 0) { + LOGE("Failed to recvmsg [%s] (%d)\n", strerror(errno), ret); + return -1; + } + + cmsg = CMSG_FIRSTHDR(&msg); + while (cmsg) { + if (cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_CREDENTIALS) + { + struct ucred *cred; + cred = (struct ucred*)CMSG_DATA(cmsg); + *sender_pid = cred->pid; + } + + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + + return iov.iov_len; +} + + + +int secom_destroy(int handle) +{ + if (close(handle) < 0) { + LOGE("Failed to close a handle\n"); + return -1; + } + return 0; +} + + + +#undef _GNU_SOURCE +// End of a file diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..45201b2 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,3 @@ +all: + @gcc homescreen.c -o homescreen `pkg-config ecore elementary shortcut --cflags --libs` + @gcc application.c -o application `pkg-config ecore elementary shortcut --cflags --libs` diff --git a/test/application.c b/test/application.c new file mode 100644 index 0000000..fd1f3b7 --- /dev/null +++ b/test/application.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static int result_cb(int ret, int pid, void *data) +{ + printf("Client: Return %d (%d)\n", ret, pid); + //elm_exit(); + return 0; +} + +static Eina_Bool shortcut_add_cb(void *data) +{ + int ret; + + ret = shortcut_add_to_home("MyName", 0, "/usr/bin/true", "/opt/share/image/what.png", result_cb, NULL); + printf("Client: shortcut_add_to_home returns: %d\n", ret); + + return ECORE_CALLBACK_RENEW; +} + +int elm_main(int argc, char *argv[]) +{ + Ecore_Timer *timer; + + timer = ecore_timer_add(3.0f, shortcut_add_cb, NULL); + if (!timer) { + printf("Failed to add a timer\n"); + } + + elm_run(); + elm_shutdown(); + + return 0; +} + +ELM_MAIN() +/* End of a file */ diff --git a/test/homescreen.c b/test/homescreen.c new file mode 100644 index 0000000..5a05357 --- /dev/null +++ b/test/homescreen.c @@ -0,0 +1,40 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.tizenopensource.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int shortcut_request_cb(const char *name, int type, const char *exec, const char *icon, int pid, void *data) +{ + printf("SERVER: name: %s, type: %d, exec: %s, icon: %s, pid: %d, data: %p\n", + name, type, exec, icon, pid, data); + return 0; +} + +int elm_main(int argc, char *argv[]) +{ + int ret; + shortcut_set_request_cb(shortcut_request_cb, NULL); + + elm_run(); + elm_shutdown(); + + return 0; +} + +ELM_MAIN() +/* End of a file */ + -- 2.7.4