From: Zofia Abramowska Date: Thu, 2 Jun 2016 10:42:46 +0000 (+0200) Subject: Adjust notification talker to work as backend X-Git-Tag: accepted/tizen/common/20160610.183543~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F72854%2F8;p=platform%2Fcore%2Fsecurity%2Faskuser.git Adjust notification talker to work as backend Change-Id: I5130aab7901c12944bb41e91a359965e318d23ce --- diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index fa184c5..11208b3 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -32,6 +32,7 @@ SET(ASKUSER_SOURCES ${ASKUSER_AGENT_PATH}/main/CynaraTalker.cpp ${ASKUSER_AGENT_PATH}/main/main.cpp ${ASKUSER_AGENT_PATH}/main/NotificationTalker.cpp + ${ASKUSER_AGENT_PATH}/ui/NotificationBackend.cpp ) INCLUDE_DIRECTORIES( diff --git a/src/agent/main/Agent.cpp b/src/agent/main/Agent.cpp index 2fcad97..6b0e8bd 100644 --- a/src/agent/main/Agent.cpp +++ b/src/agent/main/Agent.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -205,7 +206,8 @@ void Agent::processUIResponse(const Response &response) { bool Agent::startUIForRequest(Request *request) { auto data = Translator::Agent::dataToRequest(request->data()); - AskUIInterfacePtr ui(nullptr); + + AskUIInterfacePtr ui(new NotificationBackend()); auto handler = [&](RequestId requestId, UIResponseType resultType) -> void { UIResponseHandler(requestId, resultType); diff --git a/src/agent/main/NotificationTalker.cpp b/src/agent/main/NotificationTalker.cpp index 57d1f33..725a27a 100644 --- a/src/agent/main/NotificationTalker.cpp +++ b/src/agent/main/NotificationTalker.cpp @@ -37,15 +37,36 @@ namespace AskUser { namespace Agent { -NotificationTalker::NotificationTalker() +NotificationTalker::NotificationTalker() : m_failed(true), m_stopflag(false) { - m_stopflag = false; m_select.setTimeout(100); - m_sockfd = Socket::listen(Path::getSocketPath().c_str()); + try { + m_sockfd = Socket::listen(Path::getSocketPath()); + m_thread = std::thread(&NotificationTalker::run, this); + m_failed = false; + } catch (const Exception &e) { + setErrorMsg(e.what()); + } catch (const std::exception &e) { + setErrorMsg(std::string("caught std::exception: ") + e.what()); + } catch (...) { + setErrorMsg("caught unknown exception"); + } +} + +void NotificationTalker::setErrorMsg(std::string s) +{ + m_errorMsg = std::move(s); } void NotificationTalker::parseRequest(RequestType type, NotificationRequest request) { + std::lock_guard lock(m_bfLock); + + if (!m_responseHandler) { + ALOGE("Response handler not set!"); + return; + } + switch (type) { case RequestType::RT_Close: ALOGD("Close service"); @@ -66,8 +87,6 @@ void NotificationTalker::parseRequest(RequestType type, NotificationRequest requ void NotificationTalker::addRequest(NotificationRequest &&request) { - std::lock_guard lock(m_mutex); - auto &queue = m_requests[request.data.user]; auto it = std::find_if(queue.begin(), queue.end(), [&request](const NotificationRequest &req){return req.id == request.id;} @@ -82,8 +101,6 @@ void NotificationTalker::addRequest(NotificationRequest &&request) void NotificationTalker::removeRequest(RequestId id) { - std::lock_guard lock(m_mutex); - for (auto &pair : m_requests) { auto &queue = std::get<1>(pair); auto it = std::find_if(queue.begin(), queue.end(), @@ -104,15 +121,13 @@ void NotificationTalker::removeRequest(RequestId id) } } -void NotificationTalker::setResponseHandler(ResponseHandler responseHandler) -{ - m_responseHandler = responseHandler; -} - void NotificationTalker::stop() { m_stopflag = true; +} +void NotificationTalker::clear() +{ for (auto& pair : m_fdStatus) { int fd = std::get<0>(pair); Socket::close(fd); @@ -128,12 +143,9 @@ void NotificationTalker::stop() NotificationTalker::~NotificationTalker() { - for (auto& pair : m_fdStatus) { - int fd = std::get<0>(pair); - Socket::close(fd); - } - - Socket::close(m_sockfd); + stop(); + clear(); + m_thread.join(); } void NotificationTalker::sendRequest(int fd, const NotificationRequest &request) @@ -265,6 +277,8 @@ void NotificationTalker::run() try { ALOGD("Notification loop started"); while (!m_stopflag) { + std::lock_guard lock(m_bfLock); + m_select.add(m_sockfd); for (auto pair : m_userToFd) @@ -272,35 +286,41 @@ void NotificationTalker::run() int rv = m_select.exec(); - if (m_stopflag) + if (m_stopflag) { + clear(); break; + } if (rv) { newConnection(rv); recvResponses(rv); - } else { - // timeout } - /* lock_guard */ - { - std::lock_guard lock(m_mutex); - for (auto pair : m_fdStatus ) { - int fd = std::get<0>(pair); - bool b = std::get<1>(pair); - auto &queue = m_requests[m_fdToUser[fd]]; - if (b && !queue.empty()) { - NotificationRequest request = queue.front(); - sendRequest(fd, request); - } + for (auto pair : m_fdStatus ) { + int fd = std::get<0>(pair); + bool b = std::get<1>(pair); + auto &queue = m_requests[m_fdToUser[fd]]; + if (b && !queue.empty()) { + NotificationRequest request = queue.front(); + sendRequest(fd, request); } - } /* lock_guard */ + } } ALOGD("NotificationTalker loop ended"); } catch (const std::exception &e) { - ALOGE("NotificationTalker: " << e.what()); + setErrorMsg(e.what()); + m_failed = true; } catch (...) { - ALOGE("NotificationTalker: unknown error"); + setErrorMsg("unknown error"); + m_failed = true; + } + + if (m_failed && m_responseHandler) { + for (auto &queuePair : m_requests) { + for (auto &request : std::get<1>(queuePair)) { + m_responseHandler({request.id, NResponseType::Error}); + } + } } } diff --git a/src/agent/main/NotificationTalker.h b/src/agent/main/NotificationTalker.h index a6c77e7..1bed8b3 100644 --- a/src/agent/main/NotificationTalker.h +++ b/src/agent/main/NotificationTalker.h @@ -21,11 +21,13 @@ #pragma once +#include #include #include #include #include #include +#include #include #include @@ -51,15 +53,33 @@ class NotificationTalker { public: NotificationTalker(); - + bool isFailed() { return m_failed; } + std::string getErrorMsg() { return m_errorMsg; } + void setResponseHandler(ResponseHandler responseHandler) + { + m_responseHandler = responseHandler; + } void parseRequest(RequestType type, NotificationRequest request); - void run(); - void setResponseHandler(ResponseHandler responseHandler); virtual void stop(); - ~NotificationTalker(); + virtual ~NotificationTalker(); protected: + void setErrorMsg(std::string s); + void run(); + void parseResponse(NotificationResponse response, int fd); + void recvResponses(int &rv); + + void newConnection(int &rv); + void remove(int fd); + + void clear(); + + virtual void addRequest(NotificationRequest &&request); + virtual void removeRequest(RequestId id); + virtual void sendRequest(int fd, const NotificationRequest &request); + virtual void sendDismiss(int fd); + ResponseHandler m_responseHandler; UserToFdMap m_userToFd; @@ -67,25 +87,16 @@ protected: FdStatus m_fdStatus; Socket::SelectRead m_select; int m_sockfd = 0; + bool m_failed; + std::string m_errorMsg; RequestsQueue m_requests; - std::mutex m_mutex; + std::mutex m_bfLock; + std::thread m_thread; bool m_stopflag; - - void parseResponse(NotificationResponse response, int fd); - void recvResponses(int &rv); - - void newConnection(int &rv); - void remove(int fd); - - virtual void addRequest(NotificationRequest &&request); - virtual void removeRequest(RequestId id); - virtual void sendRequest(int fd, const NotificationRequest &request); - virtual void sendDismiss(int fd); }; } /* namespace Agent */ } /* namespace AskUser */ - diff --git a/src/agent/ui/NotificationBackend.cpp b/src/agent/ui/NotificationBackend.cpp new file mode 100644 index 0000000..09f01f2 --- /dev/null +++ b/src/agent/ui/NotificationBackend.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015 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 NotificationBackend.cpp + * @author Zofia Abramowska + * @brief This file contains notification backend definition. + */ + +#include +#include + +#include "NotificationBackend.h" + +namespace AskUser { + +namespace Agent { + +NotificationTalker NotificationBackend::m_notiTalker; +std::map NotificationBackend::m_idToInstance; +std::mutex NotificationBackend::m_instanceGuard; + +NotificationBackend::NotificationBackend() : m_id(-1), m_isDismissing(false) +{ + if (m_notiTalker.isFailed()) { + ALOGE("NotificationTalker failed beacause: " << m_notiTalker.getErrorMsg()); + throw std::runtime_error("Backend failed"); + } +} + +bool NotificationBackend::start(const std::string &client, const std::string &user, + const std::string &privilege, RequestId requestId, + UIResponseCallback callback) +{ + m_idToInstance[requestId] = this; + m_id = requestId; + m_cb = callback; + + if (m_notiTalker.isFailed()) { + ALOGE("NotificationTalker failed beacause: " << m_notiTalker.getErrorMsg()); + throw std::runtime_error("Backend failed"); + } + + m_notiTalker.setResponseHandler(&NotificationBackend::responseCb); + m_notiTalker.parseRequest(RequestType::RT_Action, + NotificationRequest(requestId, client, user, privilege)); + return true; +} + +void NotificationBackend::responseCb(NotificationResponse response) +{ + std::lock_guard lock(m_instanceGuard); + auto it = m_idToInstance.find(response.id); + if (it == m_idToInstance.end()) { + ALOGW("Instance for this request does not exist anymore"); + return; + } + UIResponseType type; + switch(response.response) { + case NResponseType::Allow: + type = UIResponseType::URT_YES_LIFE; + break; + case NResponseType::Deny: + type = UIResponseType::URT_NO_ONCE; + break; + case NResponseType::Never: + type = UIResponseType::URT_NO_LIFE; + break; + case NResponseType::Error: + type = UIResponseType::URT_ERROR; + break; + case NResponseType::None: + type = UIResponseType::URT_TIMEOUT; + break; + } + it->second->m_cb(response.id, type); +} + +bool NotificationBackend::setOutdated() +{ + return true; +} + +bool NotificationBackend::dismiss() +{ + m_notiTalker.parseRequest(RequestType::RT_Cancel, NotificationRequest(m_id)); + return true; +} + +bool NotificationBackend::isDismissing() const +{ + return m_isDismissing; +} + +NotificationBackend::~NotificationBackend() +{ + std::lock_guard lock(m_instanceGuard); + m_idToInstance.erase(m_id); +} + +} //namespace Agent + +} //namespace AskUser diff --git a/src/agent/ui/NotificationBackend.h b/src/agent/ui/NotificationBackend.h new file mode 100644 index 0000000..6256bf8 --- /dev/null +++ b/src/agent/ui/NotificationBackend.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 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 NotificationBackend.h + * @author Zofia Abramowska + * @brief This file contains notification backend declaration. + */ + +#pragma once + +#include +#include +#include +#include + +#include
+#include
+#include + +#include + +namespace AskUser { + +namespace Agent { + +class NotificationBackend : public AskUIInterface { +public: + NotificationBackend(); + virtual ~NotificationBackend(); + + virtual bool start(const std::string &client, const std::string &user, + const std::string &privilege, RequestId requestId, UIResponseCallback); + virtual bool setOutdated(); + virtual bool dismiss(); + virtual bool isDismissing() const; + +private: + static void responseCb(NotificationResponse response); + static NotificationTalker m_notiTalker; + static std::map m_idToInstance; + static std::mutex m_instanceGuard; + + RequestId m_id; + UIResponseCallback m_cb; + bool m_isDismissing; +}; + + typedef std::unique_ptr NotificationBackendPtr; +} // namespace Agent + +} // namespace AskUser