Add a skeleton of client API implementation 04/135804/13
authorPiotr Sawicki <p.sawicki2@partner.samsung.com>
Thu, 22 Jun 2017 11:53:56 +0000 (13:53 +0200)
committerPiotr Sawicki <p.sawicki2@partner.samsung.com>
Tue, 4 Jul 2017 11:25:31 +0000 (13:25 +0200)
Change-Id: I067a35ae6b712c7f67076e30a29efdbf0ced6d79

13 files changed:
CMakeLists.txt
packaging/askuser-notification.spec
pkgconfig/CMakeLists.txt [new file with mode: 0644]
pkgconfig/askuser-notification-client/CMakeLists.txt [new file with mode: 0644]
pkgconfig/askuser-notification-client/askuser-notification-client.pc.in [new file with mode: 0644]
src/client/CMakeLists.txt [new file with mode: 0644]
src/client/api/ApiInterface.h [new file with mode: 0644]
src/client/api/askuser-notification-client.cpp [new file with mode: 0644]
src/client/impl/ApiInterfaceImpl.cpp [new file with mode: 0644]
src/client/impl/ApiInterfaceImpl.h [new file with mode: 0644]
src/client/impl/PopupCallbackClosure.h [new file with mode: 0644]
src/client/impl/StatusCallbackClosure.h [new file with mode: 0644]
src/client/include/askuser-notification-client.h [new file with mode: 0644]

index 76ba1e0..d70618b 100644 (file)
@@ -21,7 +21,8 @@
 
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
 PROJECT("askuser")
-SET(ASKUSER_VERSION 0.1.0)
+SET(ASKUSER_VERSION_MAJOR 0)
+SET(ASKUSER_VERSION ${ASKUSER_VERSION_MAJOR}.1.13)
 
 ############################# cmake packages ##################################
 
@@ -82,11 +83,15 @@ SET(TARGET_ASKUSER_NOTIFICATION "askuser-notification")
 SET(TARGET_ASKUSER_COMMON "askuser-notification-common")
 SET(TARGET_ASKUSER_NOTIFICATION_LIB "askuser-notification-ipc")
 SET(TARGET_ASKUSER_NOTIFICATION_TEST "askuser-notification-test")
+SET(TARGET_ASKUSER_NOTIFICATION_CLIENT_LIB "askuser-notification-client")
 SET(TARGET_PLUGIN_SERVICE "askuser-plugin-service")
 ADD_SUBDIRECTORY(src/plugin)
 ADD_SUBDIRECTORY(src/notification-daemon)
 ADD_SUBDIRECTORY(src/common)
 ADD_SUBDIRECTORY(src/common/protocol)
+ADD_SUBDIRECTORY(src/client)
+
+ADD_SUBDIRECTORY(pkgconfig)
 
 IF (BUILD_WITH_SYSTEMD_DAEMON)
 ADD_SUBDIRECTORY(systemd)
index e7dd07e..9365a20 100644 (file)
@@ -67,6 +67,24 @@ Summary: Tool for testing askuser-notification
 %description test
 Tool for testing askuser-notification
 
+%package client
+Summary: Askuser notification client library
+Requires: askuser-notification-libs
+Requires(post):   /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description client
+Askuser notification client library allows to check if an application
+has a particular privilege. It also allows an application to determine privacy
+privileges. It communicates with the askuser-notification service. It is an
+asynchronous API, therefore it can be integrated with any event loop mechanism.
+
+%package client-devel
+Summary: Askuser notification client library development files
+
+%description client-devel
+Askuser notification client library development files
+
 %prep
 %setup -q
 cp -a %{SOURCE1001} .
@@ -123,6 +141,10 @@ systemctl restart cynara.service
 
 %postun libs -p /sbin/ldconfig
 
+%post client -p /sbin/ldconfig
+
+%postun client -p /sbin/ldconfig
+
 %files -f %{name}.lang
 %manifest default.manifest
 %license LICENSE
@@ -156,3 +178,13 @@ systemctl restart cynara.service
 
 %files test
 %attr(755,root,root) %{_bindir}/askuser-notification-test
+
+%files client
+%manifest default.manifest
+%license LICENSE
+%attr(644,-,-) %{_libdir}/libaskuser-notification-client.so.*
+
+%files client-devel
+%{_includedir}/askuser-notification-client/*.h
+%{_libdir}/pkgconfig/askuser-notification-client.pc
+%{_libdir}/libaskuser-notification-client.so
diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt
new file mode 100644 (file)
index 0000000..896e409
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (c) 2017 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.
+#
+# @file        CMakeLists.txt
+# @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+#
+
+ADD_SUBDIRECTORY(askuser-notification-client)
+
diff --git a/pkgconfig/askuser-notification-client/CMakeLists.txt b/pkgconfig/askuser-notification-client/CMakeLists.txt
new file mode 100644 (file)
index 0000000..491f95d
--- /dev/null
@@ -0,0 +1,26 @@
+# Copyright (c) 2017 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.
+#
+# @file        CMakeLists.txt
+# @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+#
+
+CONFIGURE_FILE(askuser-notification-client.pc.in askuser-notification-client.pc @ONLY)
+
+INSTALL(FILES
+    ${CMAKE_BINARY_DIR}/pkgconfig/askuser-notification-client/askuser-notification-client.pc
+    DESTINATION
+    ${LIB_INSTALL_DIR}/pkgconfig
+    )
+
diff --git a/pkgconfig/askuser-notification-client/askuser-notification-client.pc.in b/pkgconfig/askuser-notification-client/askuser-notification-client.pc.in
new file mode 100644 (file)
index 0000000..46bd583
--- /dev/null
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: askuser-notification-client
+Description: askuser-notification-client library
+Version: @ASKUSER_VERSION@
+Requires:
+Libs: -L${libdir} -laskuser-notification-client
+Cflags: -I${includedir}/askuser-notification-client
+
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
new file mode 100644 (file)
index 0000000..09c9049
--- /dev/null
@@ -0,0 +1,68 @@
+
+# Copyright (c) 2017 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.
+#
+# @file        CMakeLists.txt
+# @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+#
+
+SET(ASKUSER_NOTIFICATION_CLIENT_PATH ${ASKUSER_PATH}/client)
+
+PKG_CHECK_MODULES(ASKUSER_NOTIFICATION_CLIENT_DEP
+    REQUIRED
+    )
+
+INCLUDE_DIRECTORIES(SYSTEM ${ASKUSER_NOTIFICATION_CLIENT_DEP_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(
+    ${ASKUSER_NOTIFICATION_CLIENT_PATH}/api
+    ${ASKUSER_NOTIFICATION_CLIENT_PATH}/impl
+    ${ASKUSER_NOTIFICATION_CLIENT_PATH}/include
+  )
+
+SET(ASKUSER_NOTIFICATION_CLIENT_SOURCES
+    ${ASKUSER_NOTIFICATION_CLIENT_PATH}/api/askuser-notification-client.cpp
+    ${ASKUSER_NOTIFICATION_CLIENT_PATH}/impl/ApiInterfaceImpl.cpp
+   )
+
+ADD_DEFINITIONS("-fvisibility=default")
+
+ADD_LIBRARY(
+    ${TARGET_ASKUSER_NOTIFICATION_CLIENT_LIB}
+    SHARED
+    ${ASKUSER_NOTIFICATION_CLIENT_SOURCES}
+)
+
+SET_TARGET_PROPERTIES(${TARGET_ASKUSER_NOTIFICATION_CLIENT_LIB}
+    PROPERTIES
+        SOVERSION ${ASKUSER_VERSION_MAJOR}
+        VERSION ${ASKUSER_VERSION}
+        OUTPUT_NAME "askuser-notification-client"
+    )
+
+LINK_DIRECTORIES(${ASKUSER_NOTIFICATION_CLIENT_DEP_LIBRARY_DIRS})
+
+TARGET_LINK_LIBRARIES(
+    ${TARGET_ASKUSER_NOTIFICATION_CLIENT_LIB}
+    ${TARGET_ASKUSER_NOTIFICATION_LIB}
+    ${TARGET_ASKUSER_COMMON}
+    ${ASKUSER_NOTIFICATION_CLIENT_DEP_LIBRARIES}
+)
+
+INSTALL(TARGETS     ${TARGET_ASKUSER_NOTIFICATION_CLIENT_LIB}
+        DESTINATION ${LIB_INSTALL_DIR})
+
+FILE(GLOB HEADERS   ${ASKUSER_NOTIFICATION_CLIENT_PATH}/include/*.h)
+INSTALL(FILES       ${HEADERS}
+        DESTINATION ${INCLUDE_INSTALL_DIR}/askuser-notification-client)
+
diff --git a/src/client/api/ApiInterface.h b/src/client/api/ApiInterface.h
new file mode 100644 (file)
index 0000000..8c3ab54
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+/**
+ * @file        ApiInterface.h
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file contains the declaration of ApiInterface.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <PopupCallbackClosure.h>
+#include <askuser-notification-client.h>
+
+namespace AskUser {
+
+namespace Client {
+
+using RequestId = int;
+
+class ApiInterface
+{
+public:
+    virtual ~ApiInterface() {}
+
+    virtual int process(int fd, int events) = 0;
+    virtual askuser_check_result checkPrivilege(const std::string &privilege) = 0;
+    virtual RequestId popupRequest(const PopupCallbackClosure &closure,
+                                   const std::string &privilege) = 0;
+};
+
+} // namespace Client
+
+} // namespace AskUser
+
diff --git a/src/client/api/askuser-notification-client.cpp b/src/client/api/askuser-notification-client.cpp
new file mode 100644 (file)
index 0000000..803088b
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+/**
+ * @file        askuser-notification-client.cpp
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file contains the implementation of the askuser-notification client API.
+ */
+
+#include <memory>
+
+#include <ApiInterface.h>
+#include <ApiInterfaceImpl.h>
+#include <PopupCallbackClosure.h>
+#include <StatusCallbackClosure.h>
+
+#include <askuser-notification-client.h>
+
+struct askuser_client {
+    AskUser::Client::ApiInterface *impl;
+
+    askuser_client(AskUser::Client::ApiInterface *_impl) : impl(_impl) {
+    }
+
+    ~askuser_client() {
+        delete impl;
+    }
+};
+
+int askuser_client_initialize(askuser_client **pp_client,
+                              askuser_status_callback status_callback, void *p_user_data)
+{
+    if (!pp_client)
+        return ASKUSER_API_INVALID_PARAM;
+
+    try {
+        AskUser::Client::StatusCallbackClosure closure(status_callback, p_user_data);
+
+        std::unique_ptr<AskUser::Client::ApiInterface> ptr;
+        ptr.reset(new AskUser::Client::ApiInterfaceImpl(closure));
+
+        *pp_client = new askuser_client(ptr.get());
+
+        ptr.release();
+    } catch (...) {
+        // TODO handle exceptions
+        return ASKUSER_API_UNKNOWN_ERROR;
+    }
+
+    return ASKUSER_API_SUCCESS;
+}
+
+void askuser_client_finalize(askuser_client *p_client)
+{
+    if (!p_client)
+        return;
+
+    try {
+        delete p_client;
+    } catch (...) {
+        // TODO
+    }
+}
+
+int askuser_client_process(askuser_client *p_client, int fd, int events)
+{
+    if (!p_client)
+        return ASKUSER_API_INVALID_PARAM;
+
+    try {
+        return p_client->impl->process(fd, events);
+    } catch (...) {
+        // TODO
+        return ASKUSER_API_UNKNOWN_ERROR;
+    }
+}
+
+int askuser_client_check_privilege(askuser_client *p_client,
+                                   const char *privilege, askuser_check_result *p_result)
+{
+    if (!p_client || !privilege || !p_result)
+        return ASKUSER_API_INVALID_PARAM;
+
+    try {
+        *p_result = p_client->impl->checkPrivilege(privilege);
+    } catch(...) {
+        // TODO handle exceptions
+        return ASKUSER_API_UNKNOWN_ERROR;
+    }
+
+    return ASKUSER_API_SUCCESS;
+}
+
+int askuser_client_popup_request(askuser_client *p_client, const char *privilege,
+                                 askuser_popup_response_callback response_callback,
+                                 void *p_user_data, int *p_request_id)
+{
+    if (!p_client || !response_callback || !privilege)
+        return ASKUSER_API_INVALID_PARAM;
+
+    try {
+        AskUser::Client::PopupCallbackClosure closure(response_callback, p_user_data);
+        AskUser::Client::RequestId id = p_client->impl->popupRequest(closure, privilege);
+
+        if (p_request_id != nullptr) {
+            *p_request_id = id;
+        }
+    } catch (...) {
+        // TODO handle exceptions
+        return ASKUSER_API_UNKNOWN_ERROR;
+    }
+
+    return ASKUSER_API_SUCCESS;
+}
diff --git a/src/client/impl/ApiInterfaceImpl.cpp b/src/client/impl/ApiInterfaceImpl.cpp
new file mode 100644 (file)
index 0000000..ce90206
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+/**
+ * @file        ApiInterfaceImpl.cpp
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       The definition of ApiInterfaceImpl.
+ */
+
+#include "ApiInterfaceImpl.h"
+
+namespace AskUser {
+
+namespace Client {
+
+ApiInterfaceImpl::ApiInterfaceImpl(const StatusCallbackClosure &statusClosure)
+: m_statusClosure(statusClosure)
+{
+}
+
+ApiInterfaceImpl::~ApiInterfaceImpl()
+{
+    // TODO
+}
+
+int ApiInterfaceImpl::process(int fd, int events)
+{
+    // TODO
+    (void) fd;
+    (void) events;
+    return 0;
+}
+
+askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privilege)
+{
+    // TODO
+    (void) privilege;
+
+    return ASKUSER_CHECK_RESULT_DENY;
+}
+
+RequestId ApiInterfaceImpl::popupRequest(const PopupCallbackClosure &closure,
+                                         const std::string &privilege)
+{
+    // TODO
+    (void) closure;
+    (void) privilege;
+
+    return 0;
+}
+
+} // namespace Client
+
+} // namespace AskUser
diff --git a/src/client/impl/ApiInterfaceImpl.h b/src/client/impl/ApiInterfaceImpl.h
new file mode 100644 (file)
index 0000000..e255ac2
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+/**
+ * @file        ApiInterfaceImpl.h
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       The declaration of ApiInterfaceImpl.
+ */
+
+#pragma once
+
+#include <ApiInterface.h>
+#include <PopupCallbackClosure.h>
+#include <StatusCallbackClosure.h>
+
+#include <askuser-notification-client.h>
+
+namespace AskUser {
+
+namespace Client {
+
+class ApiInterfaceImpl : public AskUser::Client::ApiInterface {
+public:
+    ApiInterfaceImpl(const AskUser::Client::StatusCallbackClosure &closure);
+    ApiInterfaceImpl(const ApiInterfaceImpl& orig) = delete;
+    virtual ~ApiInterfaceImpl();
+
+    ApiInterface &operator=(const ApiInterfaceImpl& orig) = delete;
+
+    virtual int process(int fd, int events);
+    virtual askuser_check_result checkPrivilege(const std::string &privilege);
+    virtual RequestId popupRequest(const AskUser::Client::PopupCallbackClosure &closure,
+                                   const std::string &privilege);
+
+private:
+    AskUser::Client::StatusCallbackClosure m_statusClosure;
+};
+
+} // namespace Client
+
+} // namespace AskUser
+
diff --git a/src/client/impl/PopupCallbackClosure.h b/src/client/impl/PopupCallbackClosure.h
new file mode 100644 (file)
index 0000000..ebdf0ee
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+/**
+ * @file        PopupCallbackClosure.h
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       The definition of PopupCallbackClosure.
+ */
+
+#pragma once
+
+#include <askuser-notification-client.h>
+
+namespace AskUser {
+
+namespace Client {
+
+class PopupCallbackClosure {
+public:
+    PopupCallbackClosure(askuser_popup_response_callback callback, void *userData)
+    : m_callback(callback)
+    , m_userData(userData)
+    {}
+
+    void operator()(int requestId, askuser_call_cause cause, askuser_popup_result result) const
+    {
+        m_callback(requestId, cause, result, m_userData);
+    }
+
+private:
+    askuser_popup_response_callback m_callback;
+    void *m_userData;
+};
+
+} // namespace Client
+
+} // namespace AskUser
+
diff --git a/src/client/impl/StatusCallbackClosure.h b/src/client/impl/StatusCallbackClosure.h
new file mode 100644 (file)
index 0000000..8a51189
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+/**
+ * @file        StatusCallbackClosure.h
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       The definition of StatusCallbackClosure.
+ */
+
+#pragma once
+
+#include <askuser-notification-client.h>
+
+namespace AskUser {
+
+namespace Client {
+
+class StatusCallbackClosure {
+public:
+    StatusCallbackClosure(askuser_status_callback callback, void *userData)
+    : m_callback(callback)
+    , m_userData(userData)
+    {}
+
+    void operator()(int fd, int events) const
+    {
+        m_callback(fd, events, m_userData);
+    }
+
+private:
+    askuser_status_callback m_callback;
+    void *m_userData;
+};
+
+} // namespace Client
+
+} // namespace AskUser
+
diff --git a/src/client/include/askuser-notification-client.h b/src/client/include/askuser-notification-client.h
new file mode 100644 (file)
index 0000000..c1b6df7
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+/**
+ * @file        askuser-notification-client.h
+ * @author      Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @version     1.0
+ * @brief       The declaration of the askuser-notification client API.
+ */
+
+#ifndef ASKUSER_NOTIFICATION_CLIENT_H
+#define ASKUSER_NOTIFICATION_CLIENT_H
+
+/**
+ * \name Status return codes
+ * @{
+ */
+
+/*! \brief indicating that the call was successful */
+#define ASKUSER_API_SUCCESS 0
+
+/*! \brief indicating that an unknown error occurred */
+#define ASKUSER_API_UNKNOWN_ERROR -1
+
+/*! \brief indicating that a memory allocation failed */
+#define ASKUSER_API_OUT_OF_MEMORY -2
+
+/*! \brief indicating that an invalid parameter was passed */
+#define ASKUSER_API_INVALID_PARAM -3
+
+/*! \brief indicating that a connection error occurred */
+#define ASKUSER_API_CONNECTION_ERROR -4
+
+/** @} */
+
+/**
+ * \name Types of file descriptor events
+ *
+ * @{
+ */
+
+/*! \brief a file descriptor is ready to read */
+#define ASKUSER_READ_EVENT  (1 << 0)
+
+/*! \brief a file descriptor is ready to write */
+#define ASKUSER_WRITE_EVENT (1 << 1)
+
+/*! \brief an error has been detected on a file descriptor by an event loop or
+ *         the API wants to inform that a file descriptor is to be closed
+ */
+#define ASKUSER_EMPTY_EVENTS 0
+
+/** @} */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct askuser_client askuser_client;
+
+/**
+ * \enum askuser_check_result
+ * Values indicating the result of an askuser_client_check_privilege() call.
+ *
+ * \var askuser_check_result::ASKUSER_CHECK_RESULT_ALLOW
+ * An application has a privilege.
+ *
+ * \var askuser_check_result::ASKUSER_CHECK_RESULT_DENY
+ * An application does not have a privilege.
+ *
+ * \var askuser_check_result::ASKUSER_CHECK_RESULT_ASK
+ * A user should be asked about whether grant privilege to an application or not.
+ */
+typedef enum {
+    ASKUSER_CHECK_RESULT_ALLOW,
+    ASKUSER_CHECK_RESULT_DENY,
+    ASKUSER_CHECK_RESULT_ASK,
+} askuser_check_result;
+
+/**
+ * \enum askuser_popup_result
+ * Values returned by popup.
+ *
+ * \var askuser_popup_result::ASKUSER_POPUP_RESULT_ALLOW_FOREVER
+ * A user granted a privilege to an application.
+ *
+ * \var askuser_popup_result::ASKUSER_POPUP_RESULT_DENY_FOREVER
+ * A user did not grant a privilege to an application.
+ *
+ * \var askuser_popup_result::ASKUSER_POPUP_RESULT_DENY_ONCE
+ * A user did not grant a privilege to an application for this
+ * particular query.
+ */
+typedef enum {
+    ASKUSER_POPUP_RESULT_ALLOW_FOREVER,
+    ASKUSER_POPUP_RESULT_DENY_FOREVER,
+    ASKUSER_POPUP_RESULT_DENY_ONCE,
+} askuser_popup_result;
+
+/**
+ * \enum askuser_call_cause
+ * Values indicating the reason passed to askuser_popup_response_callback.
+ *
+ * \var askuser_call_cause::ASKUSER_CALL_CAUSE_ANSWER
+ * Callback was called with a valid answer.
+ *
+ * \var askuser_call_cause::ASKUSER_CALL_CAUSE_ERROR
+ * Callback was called because of an error.
+ *
+ * \var askuser_call_cause::ASKUSER_CALL_CAUSE_FINALIZE
+ * Callback was called because askuser_client_finalize() had been called.
+ */
+typedef enum {
+    ASKUSER_CALL_CAUSE_ANSWER,
+    ASKUSER_CALL_CAUSE_ERROR,
+    ASKUSER_CALL_CAUSE_FINALIZE,
+} askuser_call_cause;
+
+
+/**
+ * \brief This callback function is called when the status of a file descriptor changes.
+ *
+ * A file descriptor changes when a client:
+ * - is ready to send a request (after calling: askuser_client_popup_request())
+ * - is ready to receive a response
+ *
+ * This function is crucial to implement an asynchronous API. An application should
+ * register its askuser_status_callback function to monitor file descriptors.
+ * In the body of this callback function, the application should configure its
+ * I/O multiplexing mechanism (select, poll, GLib main loop etc.) to wait for specified
+ * events (events parameter) which may occur on a file descriptor (fd parameter).
+ *
+ * \attention This callback is called from the askuser_client_process() function context.
+ *
+ * \attention The events and fd parameters passed in this callback should be
+ * stored on the application side. Application should use this stored information
+ * in every event loop cycle to configure its I/O multiplexing mechanism.
+ * It is due to the fact that the callback may not be called in every loop cycle for every
+ * askuser_client_process() call. For example, if the API wants to send some data,
+ * it calls the callback with the 'events' param having the ASKUSER_WRITE_EVENT flag set.
+ * Then, askuser_client_process() may be called multiple times until the data is sent.
+ * When this task is done, the callback is called with cleared ASKUSER_WRITE_EVENT,
+ * which means that the application should stop waiting for the WRITE event.
+ *
+ * Have a look at the below simplified code (managing of fd is ommited for better
+ * readability).
+ *
+ * \code
+ * int app_events_to_wait_for;
+ *
+ * void callback(int fd, int events, void *p_user_data)
+ * {
+ *     app_events_to_wait_for = events;
+ * }
+ *
+ * void event_loop()
+ * {
+ *    for (;;) {
+ *        detected_events = wait_for_events(app_events_to_wait_for);
+ *        askuser_client_process(client, fd, detected_events);
+ *    }
+ * }
+ * \endcode
+ *
+ * \param[in]   fd          A file descriptor.
+ * \param[in]   events      It is a bit-field value compounds of ASKUSER_READ_EVENT
+ *                          or ASKUSER_WRITE_EVENT or both.
+ *                          Special value ASKUSER_EMPTY_EVENTS indicates that the
+ *                          file descriptor (fd) should be removed from a file
+ *                          descriptor set of an event loop mechanism.
+ * \param[in]   p_user_data User specific data passed to askuser_client_initialize().
+ */
+typedef void (*askuser_status_callback) (int fd, int events, void *p_user_data);
+
+/**
+ * \brief This callback function is called when a client receives a response
+ * upon calling askuser_client_popup_request().
+ *
+ * \attention This callback is called from the askuser_client_process() function context.
+ *
+ * \param[in]   request_id  A number identifying the request. It will be equal to
+ *                          the value of *p_request_id generated by a corresponding
+ *                          askuser_client_popup_request() function call.
+ * \param[in]   cause       A value representing the reason why this callback has
+ *                          been called.
+ * \param[in]   result      It is a result of response to request created by
+ *                          askuser_client_popup_request(). This should be
+ *                          interpreted as a valid value only if cause is equal to
+ *                          askuser_call_cause::ASKUSER_CALL_CAUSE_ANSWER.
+ * \param[in]   p_user_data User specific data, this parameter was previously
+ *                          passed to askuser_client_popup_request().
+ */
+typedef void (*askuser_popup_response_callback) (int request_id,
+                                                 askuser_call_cause cause,
+                                                 askuser_popup_result result,
+                                                 void *p_user_data);
+
+/**
+ * \brief Description
+ * Initialize askuser-notification client. It allocates structure and
+ * initializes it using a given status callback and user data.
+ *
+ * \par Purpose:
+ * This API function must be called prior to any call of the other
+ * askuser-notification client functions.
+ *
+ * \par Typical use case:
+ * It should be called before entering an event loop and before calling any
+ * other askuser-notification client API function.
+ *
+ * \par Method of function operation:
+ * This API function initializes inner library structures and in case of success
+ * returns askuser_client structure.
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread-safety:
+ * This function is NOT thread-safe.
+ *
+ * \par Important notes:
+ * Structure askuser_client created by a askuser_client_initialize() call
+ * should be released by calling askuser_client_finalize().
+ *
+ * \param[out]  pp_client       A placeholder for a newly created askuser_client
+ *                              structure. The pp_client is valid only if this
+ *                              function returns ASKUSER_API_SUCCESS.
+ * \param[in]   status_callback A callback function which will be called every
+ *                              time when some file descriptor belonging to the
+ *                              askuser_client structure changes its state.
+ * \param[in]   p_user_data     User specific data which will be passed to the
+ *                              status_callback function.
+ *                              Set NULL if you don't use user data.
+ *
+ * \return ASKUSER_API_SUCCESS on success
+ * \return a negative value in case of an error (see "Status return codes")
+ */
+int askuser_client_initialize(askuser_client **pp_client,
+                              askuser_status_callback status_callback,
+                              void *p_user_data);
+
+/**
+ * \brief Description
+ * Release instance of the askuser_client structure. It releases all resources
+ * associated with askuser_client structure.
+ *
+ * \par Purpose:
+ * This API function must be called to release all resources associated with
+ * askuser_client structure.
+ *
+ * \par Typical use case:
+ * This API function should be called when the askuser-notification client
+ * functionality is no more used by an application
+ * (e.g. when the application finishes).
+ *
+ * \par Method of function operation:
+ * This API function releases all internal resources and deallocates the
+ * askuser_client structure. When there are pending requests, registered
+ * askuser_response_callback functions will be called with an appropriate
+ * status code: askuser_call_cause::ASKUSER_CALL_CAUSE_FINALIZE.
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread-safety:
+ * This function is NOT thread-safe.
+ *
+ * \par Important notes:
+ * After calling this function on a particular askuser_client structure,
+ * no subsequent calls of askuser_client_finalize() should be performed on
+ * the same structure.
+ *
+ * \param[out]  p_client    An instance of the askuser_client structure,
+ *                          previously created by askuser_client_initialize().
+ */
+void askuser_client_finalize(askuser_client *p_client);
+
+/**
+ * \brief Description
+ * This function process R/W events that occurred on a file descriptor associated
+ * with a specific askuser_client structure. All statuses and errors which occur
+ * on the file descriptor will be passed to a callback function registered by
+ * invoking askuser_client_initialize().
+ *
+ * \par Purpose:
+ * This API function is called to process read and write events which occurred
+ * on a file descriptor. In result of calling this function an appropriate
+ * callback is executed: askuser_status_callback or askuser_popup_response_callback.
+ *
+ * \par Typical use case:
+ * The event loop of an application waits for events which may occur on file descriptors
+ * previously registered by askuser_status_callback. When an event occurs then the event
+ * loop should call this function passing an askuser_client structure, a file
+ * descriptor on which the event occurred and events (a bit-field value compounds of
+ * ASKUSER_READ_EVENT and ASKUSER_WRITE_EVENT).
+ *
+ * \par Method of function operation:
+ * \parblock
+ * This function sends pending requests (ASKUSER_WRITE_EVENT), receives all responses
+ * from the askuser-notification service (ASKUSER_READ_EVENT). In result of these
+ * actions an appropriate callback is executed (askuser_popup_response_callback,
+ * or askuser_status_callback).
+ * \endparblock
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread-safety:
+ * This function is NOT thread-safe.
+ *
+ * \param[in]   p_client    An instance of the askuser_client structure, previously
+ *                          created by askuser_client_initialize().
+ * \param[in]   fd          A file descriptor.
+ * \param[in]   events      It is a bit-field value compounds of ASKUSER_READ_EVENT
+ *                          and ASKUSER_WRITE_EVENT, which represents the detected
+ *                          events on that fd. The event loop mechanism should
+ *                          pass **ASKUSER_EMPTY_EVENTS** if it detects an error
+ *                          on the file descriptor.
+ *
+ * \return ASKUSER_API_SUCCESS on success
+ * \return a negative value in case of an error (see "Status return codes")
+ */
+int askuser_client_process(askuser_client *p_client, int fd, int events);
+
+/**
+ * \brief Description
+ * This function is called to check if an application has access to a particular
+ * privilege.
+ *
+ * \par Purpose:
+ * This API function should be called if an application wants to check if it has
+ * access to a given privilege.
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread-safety:
+ * This function is NOT thread-safe.
+ *
+ * \param[in]   p_client    An instance of the askuser_client structure previously
+ *                          created by askuser_client_initialize().
+ * \param[in]   privilege   Privilege that is to be checked.
+ * \param[out]  p_result    The result of a privilege check.
+ *
+ * \return ASKUSER_API_SUCCESS on success
+ * \return a negative value in case of an error (see "Status return codes")
+ */
+int askuser_client_check_privilege(askuser_client *p_client, const char *privilege,
+                                   askuser_check_result *p_result);
+
+/**
+ * \brief Description
+ * This function is called to determine a privacy privilege .
+ *
+ * \par Purpose:
+ * This API function should be called if an application wants to determine a privacy
+ * privilege. When this function is called, the askuser-notification service shows
+ * an appropriate UI dialog box (popup) with a question. After user's decision, the
+ * service modifies sends the response back to the application.
+ * The application is informed about user's decision by calling
+ * askuser_popup_response_callback.
+ *
+ * \par Method of function operation:
+ * If the result of calling askuser_client_check_privilege() is
+ * askuser_check_result::ASKUSER_CHECK_RESULT_ASK, the application should call
+ * this function to determine whether a user allows an application to use
+ * a particular privilege.
+ *
+ * \par Sync (or) Async:
+ * This is an asynchronous API.
+ *
+ * \par Thread-safety:
+ * This function is NOT thread-safe.
+ *
+ * \param[in]   p_client            An instance of the askuser_client structure
+ *                                  previously created by askuser_client_initialize().
+ * \param[in]   privilege           A privilege for which a popup must be shown.
+ * \param[in]   response_callback   A callback function called when the API receives
+ *                                  a response.
+ * \param[in]   p_user_data         User specific data which will be passed to
+ *                                  the registered response_callback.
+ *                                  Set to NULL if you don't use user data.
+ * \param[out]  p_request_id        An identifier of a request generated by the API.
+ *                                  Set NULL if you don't use a request ID.
+ *
+ * \return ASKUSER_API_SUCCESS on success
+ * \return a negative value in case of an error (see "Status return codes")
+ */
+int askuser_client_popup_request(askuser_client *p_client, const char *privilege,
+                                 askuser_popup_response_callback response_callback,
+                                 void *p_user_data, int *p_request_id);
+
+/**
+ * Example
+ *
+ * NOTICE: Everything with app prefix is a part of a hypothetical
+ * application framework.
+ *
+ * \code
+ * void ask_status_callback(int fd, int events, void *p_user_data)
+ * {
+ *     assert(p_user_data != NULL);
+ *     app_context *app = (app_context *) p_user_data;
+ *     // Note that events == 0 means that this fd should be
+ *     // removed from a monitored file descriptor set.
+ *     app_update_fds(app, fd, app_askuser_to_app_events(events));
+ * }
+ *
+ * void ask_popup_response_callback(int request_id, askuser_call_cause cause,
+ *                              askuser_popup_result result, void *p_user_data)
+ * {
+ *     assert(p_user_data != NULL);
+ *     app_context *app = (app_context *) p_user_data;
+ *     app_callback callback = app_get_callback(app, request_id);
+ *
+ *     switch (cause) {
+ *         case ASKUSER_CALL_CAUSE_ANSWER:
+ *             callback(app, askuser_to_app_popup_result(result));
+ *             break;
+ *         case ASKUSER_CALL_CAUSE_FINALIZE:
+ *             callback(app, APP_IS_CLOSING);
+ *             break;
+ *         case ASKUSER_CALL_CAUSE_ERROR:
+ *             // handle errors
+ *             callback(app, APP_ASKUSER_ERROR_OCCURED);
+ *             break;
+ *     }
+ *
+ *     app_unregister_callback(app, request_id);
+ * }
+ *
+ * void app_check_privilege(app_context *app, const char *privilege, app_callback callback);
+ * {
+ *     int status;
+ *     int request_id;
+ *     askuser_check_result result;
+ *
+ *     assert(app != NULL);
+ *     askuser_client *client = app_get_askuser_client(app);
+ *
+ *     status = askuser_client_check_privilege(client, &result);
+ *     if (status != ASKUSER_API_SUCCESS) {
+ *         // handle errors
+ *         return;
+ *     }
+ *
+ *     switch (result) {
+ *         case ASKUSER_CHECK_RESULT_ALLOW:
+ *             // adjust GUI to reflect that the app has access to a
+ *             // specific resource
+ *             break;
+ *         case ASKUSER_CHECK_RESULT_DENY:
+ *             // adjust GUI to reflect that the app doesn't have access to a
+ *             // specific resource
+ *             break;
+ *         case ASKUSER_CHECK_RESULT_ASK:
+ *             status = askuser_client_popup_request(client, privilege,
+ *                  ask_popup_response_callback, app, &request_id);
+ *             if (status != ASKUSER_API_SUCCESS) {
+ *                 //handle errors
+ *                 return;
+ *             }
+ *             app_register_callback(app, callback, request_id);
+ *             break;
+ *     }
+ * }
+ *
+ *
+ * void main_loop(app_context *app)
+ * {
+ *     int status
+ *     int fd;
+ *     askuser_client *client = NULL;
+ *
+ *     assert(app != NULL);
+ *
+ *     status = askuser_client_initialize(&client, ask_status_callback, app);
+ *      if (status != ASKUSER_API_SUCCESS) {
+ *         // handle errors
+ *         return;
+ *     }
+ *
+ *     app_set_askuser_client(app, client);
+ *
+ *     // event loop
+ *     for (;;) {
+ *         app_wait_for_events(app);
+ *
+ *         app_for_each_active_fd(app, fd) {
+ *             if (app_is_askuser_fd(app, fd)) {
+ *                 app_events events = app_get_fd_events(app, fd);
+ *                 askuser_client_process(client, fd, app_to_askuser_events(events));
+ *             }
+ *             // process other file descriptors not related to askuser
+ *         }
+ *     }
+ *
+ *     askuser_client_finalize(client);
+ * }
+ * \endcode
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ASKUSER_NOTIFICATION_CLIENT_H */