* @brief This file implements main class of ask user agent
*/
+#include <memory>
+#include <sstream>
+#include <string>
#include <unistd.h>
#include <utility>
std::unique_lock<std::mutex> 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
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");
}
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<std::mutex> 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
#include <map>
#include <mutex>
#include <queue>
+#include <types/PolicyType.h>
#include <main/CynaraTalker.h>
#include <main/Request.h>
+#include <main/Response.h>
+
+#include <ui/AskUIInterface.h>
namespace AskUser {
CynaraTalker m_cynaraTalker;
std::map<RequestId, Request *> m_requests;
std::queue<Request *> m_incomingRequests;
+ std::queue<Response> m_incomingResponses;
std::condition_variable m_event;
std::mutex m_mutex;
static volatile sig_atomic_t m_stopFlag;
+ std::map<RequestId, AskUIInterfacePtr> m_UIs;
void init();
void finish();
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
--- /dev/null
+/*
+ * 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 <a.malinowsk2@partner.samsung.com>
+ * @brief This file declares class representing response from user interface
+ */
+
+#pragma once
+
+#include <main/Request.h>
+#include <ui/AskUIInterface.h>
+
+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
--- /dev/null
+/*
+ * 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 <a.malinowsk2@partner.samsung.com>
+ * @brief This file contains ask user UI interface declaration.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <main/Request.h>
+
+namespace AskUser {
+
+namespace Agent {
+
+typedef enum {
+ URT_YES,
+ URT_NO,
+ URT_SESSION,
+ URT_TIMEOUT,
+ URT_ERROR
+} UIResponseType;
+
+typedef std::function<void(RequestId, UIResponseType)> 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<AskUIInterface> AskUIInterfacePtr;
+
+} // namespace Agent
+
+} // namespace AskUser