From bbb7a44dd788d8f76776b7eed83847f779db4fcc Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 2 Dec 2014 14:52:40 +0100 Subject: [PATCH] Add UI handling This patch introduces user interface related stuff, implements creating UIs and handling responses from them. Change-Id: I8899ead4d4b6222bf6c50bb51a2703502e2f7210 --- src/agent/main/Agent.cpp | 134 ++++++++++++++++++++++++++++++++----- src/agent/main/Agent.h | 13 ++++ src/agent/main/Response.h | 53 +++++++++++++++ src/agent/ui/AskUIInterface.h | 59 ++++++++++++++++ src/common/types/AgentErrorMsg.cpp | 3 +- src/common/types/AgentErrorMsg.h | 3 +- 6 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 src/agent/main/Response.h create mode 100644 src/agent/ui/AskUIInterface.h diff --git a/src/agent/main/Agent.cpp b/src/agent/main/Agent.cpp index 477428c..89aaa04 100644 --- a/src/agent/main/Agent.cpp +++ b/src/agent/main/Agent.cpp @@ -19,6 +19,9 @@ * @brief This file implements main class of ask user agent */ +#include +#include +#include #include #include @@ -57,28 +60,48 @@ void Agent::run() { std::unique_lock lock(m_mutex); m_event.wait(lock); - while (!m_incomingRequests.empty()) { - Request *request = m_incomingRequests.front(); - m_incomingRequests.pop(); - lock.unlock(); + while (!m_incomingRequests.empty() || !m_incomingResponses.empty()) { + + if (!m_incomingRequests.empty()) { + Request *request = m_incomingRequests.front(); + m_incomingRequests.pop(); + lock.unlock(); + + LOGD("Request popped from queue:" + " type [" << request->type() << "]," + " id [" << request->id() << "]," + " data length [" << request->data().size() << "]"); - LOGD("Request popped from queue:" - " type [" << request->type() << "]," - " id [" << request->id() << "]," - " data length [" << request->data().size() << "]"); + if (request->type() == RT_Close) { + delete request; + m_stopFlag = 1; + break; + } - if (request->type() == RT_Close) { - delete request; - m_stopFlag = 1; - break; + processCynaraRequest(request); + + lock.lock(); } - processCynaraRequest(request); + if (!m_incomingResponses.empty()) { + Response response = m_incomingResponses.front(); + m_incomingResponses.pop(); + lock.unlock(); + + LOGD("Response popped from queue:" + " type [" << response.type() << "]," + " id [" << response.id() << "]"); + processUIResponse(response); + + lock.lock(); + } + + lock.unlock(); + cleanupUIThreads(); lock.lock(); } - //TODO: do sth here with available data from UIs } //TODO: dismiss all threads if possible @@ -112,7 +135,7 @@ void Agent::processCynaraRequest(Request *request) { delete existingRequest->second; m_requests.erase(existingRequest); m_cynaraTalker.sendResponse(request->type(), request->id()); - //TODO: get UI for request and dismiss or update it + dismissUI(request->id()); } else { LOGE("Incoming request with ID: [" << request->id() << "] is being already processed"); } @@ -134,9 +157,84 @@ void Agent::processCynaraRequest(Request *request) { requestPtr.release(); } -bool Agent::startUIForRequest(Request *request UNUSED) { - // TODO: start UI for request - return false; +void Agent::processUIResponse(const Response &response) { + auto requestIt = m_requests.find(response.id()); + if (requestIt != m_requests.end()) { + Cynara::PluginData pluginData; + if (response.type() == URT_ERROR) { + pluginData = Translator::Agent::answerToData(Cynara::PolicyType(), + AgentErrorMsg::Error); + } else if (response.type() == URT_TIMEOUT) { + pluginData = Translator::Agent::answerToData(Cynara::PolicyType(), + AgentErrorMsg::Timeout); + } else { + pluginData = Translator::Agent::answerToData( + UIResponseToPolicyType(response.type()), + AgentErrorMsg::NoError); + } + m_cynaraTalker.sendResponse(RT_Action, requestIt->second->id(), pluginData); + delete requestIt->second; + m_requests.erase(requestIt); + } + + dismissUI(response.id()); +} + +bool Agent::startUIForRequest(Request *request) { + auto data = Translator::Agent::dataToRequest(request->data()); + AskUIInterfacePtr ui; // TODO: create pointer to backend + + auto handler = [&](RequestId requestId, UIResponseType resultType) -> void { + UIResponseHandler(requestId, resultType); + }; + bool ret = ui->start(data.client, data.user, data.privilege, request->id(), handler); + if (ret) { + m_UIs.insert(std::make_pair(request->id(), std::move(ui))); + } + return ret; +} + +void Agent::UIResponseHandler(RequestId requestId, UIResponseType responseType) { + LOGD("UI response received: type [" << responseType << "], id [" << requestId << "]"); + + std::unique_lock lock(m_mutex); + m_incomingResponses.push(Response(requestId, responseType)); + m_event.notify_one(); +} + +bool Agent::cleanupUIThreads() { + bool ret = true; + for (auto it = m_UIs.begin(); it != m_UIs.end();) { + if (it->second->isDismissing() && it->second->dismiss()) { + it = m_UIs.erase(it); + } else { + ret = false; + ++it; + } + } + return ret; +} + +void Agent::dismissUI(RequestId requestId) { + auto it = m_UIs.find(requestId); + if (it != m_UIs.end()) { + if (it->second->dismiss()) { + it = m_UIs.erase(it); + } + } +} + +Cynara::PolicyType Agent::UIResponseToPolicyType(UIResponseType responseType) { + switch (responseType) { + case URT_YES: + return AskUser::SupportedTypes::Client::ALLOW_ONCE; + case URT_SESSION: + return AskUser::SupportedTypes::Client::ALLOW_PER_SESSION; + case URT_NO: + return Cynara::PredefinedPolicyType::DENY; + default: + return Cynara::PredefinedPolicyType::DENY; + } } } // namespace Agent diff --git a/src/agent/main/Agent.h b/src/agent/main/Agent.h index 6df7c72..a1ce240 100644 --- a/src/agent/main/Agent.h +++ b/src/agent/main/Agent.h @@ -26,9 +26,13 @@ #include #include #include +#include #include
#include
+#include
+ +#include namespace AskUser { @@ -49,9 +53,11 @@ private: CynaraTalker m_cynaraTalker; std::map m_requests; std::queue m_incomingRequests; + std::queue m_incomingResponses; std::condition_variable m_event; std::mutex m_mutex; static volatile sig_atomic_t m_stopFlag; + std::map m_UIs; void init(); void finish(); @@ -59,6 +65,13 @@ private: void requestHandler(Request *request); void processCynaraRequest(Request *request); bool startUIForRequest(Request *request); + void UIResponseHandler(RequestId requestId, UIResponseType responseType); + + void processUIResponse(const Response &response); + bool cleanupUIThreads(); + void dismissUI(RequestId requestId); + + static Cynara::PolicyType UIResponseToPolicyType(UIResponseType responseType); }; } // namespace Agent diff --git a/src/agent/main/Response.h b/src/agent/main/Response.h new file mode 100644 index 0000000..cb20353 --- /dev/null +++ b/src/agent/main/Response.h @@ -0,0 +1,53 @@ +/* + * 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 Response.h + * @author Adam Malinowski + * @brief This file declares class representing response from user interface + */ + +#pragma once + +#include
+#include + +namespace AskUser { + +namespace Agent { + +class Response { +public: + Response() = default; + Response(RequestId requestId, UIResponseType responseType) : m_id(requestId), + m_type(responseType) {} + ~Response() {} + + RequestId id() const { + return m_id; + } + + UIResponseType type() const { + return m_type; + } + +private: + RequestId m_id; + UIResponseType m_type; +}; + +} // namespace Agent + +} // namespace AskUser diff --git a/src/agent/ui/AskUIInterface.h b/src/agent/ui/AskUIInterface.h new file mode 100644 index 0000000..b78c35a --- /dev/null +++ b/src/agent/ui/AskUIInterface.h @@ -0,0 +1,59 @@ +/* + * 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 AskUIInterface.h + * @author Adam Malinowski + * @brief This file contains ask user UI interface declaration. + */ + +#pragma once + +#include +#include +#include + +#include
+ +namespace AskUser { + +namespace Agent { + +typedef enum { + URT_YES, + URT_NO, + URT_SESSION, + URT_TIMEOUT, + URT_ERROR +} UIResponseType; + +typedef std::function UIResponseCallback; + +class AskUIInterface { +public: + virtual ~AskUIInterface() {}; + + virtual bool start(const std::string &client, const std::string &user, + const std::string &privilege, RequestId requestId, UIResponseCallback) = 0; + virtual bool setOutdated() = 0; + virtual bool dismiss() = 0; + virtual bool isDismissing() = 0; +}; + +typedef std::unique_ptr AskUIInterfacePtr; + +} // namespace Agent + +} // namespace AskUser diff --git a/src/common/types/AgentErrorMsg.cpp b/src/common/types/AgentErrorMsg.cpp index 983a84f..2fd5e71 100644 --- a/src/common/types/AgentErrorMsg.cpp +++ b/src/common/types/AgentErrorMsg.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co. + * Copyright (c) 2014-2015 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ namespace AskUser { namespace AgentErrorMsg { +const std::string NoError = ""; const std::string Error = "ERROR"; const std::string Timeout = "TIMEOUT"; diff --git a/src/common/types/AgentErrorMsg.h b/src/common/types/AgentErrorMsg.h index 6b7dcaa..842414d 100644 --- a/src/common/types/AgentErrorMsg.h +++ b/src/common/types/AgentErrorMsg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co. + * Copyright (c) 2014-2015 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ namespace AskUser { namespace AgentErrorMsg { +extern const std::string NoError; extern const std::string Error; extern const std::string Timeout; -- 2.7.4