* limitations under the License
*/
/**
- * @file src/notification-daemon/GuiRunner.h
+ * @file src/agent/notification-daemon/AskUserTalker.cpp
* @author Oskar Świtalski <o.switalski@samsung.com>
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
* @brief Definition of AskUserTalker class
*/
#include "AskUserTalker.h"
-#include <iostream>
+#include <signal.h>
#include <string>
+#include <sys/signalfd.h>
#include "Policy.h"
#include "PrivilegeInfo.h"
#include <socket/Socket.h>
#include <socket/Poll.h>
#include <types/NotificationResponse.h>
-#include <types/Protocol.h>
#include <types/NotificationRequest.h>
#include <exception/ErrnoException.h>
#include <exception/Exception.h>
#include <security-manager.h>
+#ifdef BUILD_WITH_SYSTEMD_DAEMON
+#include <systemd/sd-daemon.h>
+#endif
namespace AskUser {
ALOGD("SecurityManager: Setting security level to " << level);
std::string appName;
identifyApp(app, appName);
+ if (appName.empty()) {
+ ALOGE("Couldn't fetch appName from cynara client. Cannot set policy");
+ return;
+ }
std::string privacyName = PrivilegeInfo::getPrivacyName(perm);
if (privacyName.empty()) {
} /* namespace */
+void AskUserTalker::dissmissCb(int fd, void *data) {
+ AskUserTalker *talker = static_cast<AskUserTalker*>(data);
+ if (fd == talker->m_currentPeerSocket.getFd()) {
+ ALOGD("Client behaved incorrectly");
+ // I would close client socket here but ecore loop doesn't like closing fd while in handler
+ } else if (fd == talker->m_signalSocket.getFd()) {
+ ALOGD("Got signal to close");
+ talker->m_running = false;
+ }
+}
+
+AskUserTalker::AskUserTalker()
+ : m_poller(2),
+ m_signalSocket(Socket::PeerType::SIGNAL),
+ m_serverSocket(Socket::PeerType::SERVER),
+ m_currentPeerSocket(Socket::PeerType::PEER)
+{}
+
+void AskUserTalker::setSignalDescriptor() {
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+
+ if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) {
+ throw ErrnoException("Couldn't set signal mask");
+ }
+
+ int signalFd = signalfd(-1, &mask, 0);
+ if (signalFd < 0) {
+ throw ErrnoException("Couldn't create signalfd");
+ }
+
+ m_signalSocket.setFd(signalFd);
+ m_poller.setEvents(m_signalSocket.getFd(), POLLIN);
+
+ ALOGD("Signal descriptor set for " << m_signalSocket.getFd());
+}
+
+void AskUserTalker::init() {
+#ifdef BUILD_WITH_SYSTEMD_DAEMON
+ int systemdFdCount = sd_listen_fds(0);
+ if (systemdFdCount < 0) {
+ ALOGE("Error in sd_listen_fds");
+ throw Exception("Couldn't setup systemd socket");
+ }
+ if (systemdFdCount > 1) {
+ ALOGE("Systemd passed to many sockets");
+ throw Exception("Too many sockets passed");
+ }
+
+ m_serverSocket.setFd(SD_LISTEN_FDS_START);
+ if (m_serverSocket.getFd() == -1) {
+ ALOGE("Failed to set socket fd from systemd");
+ throw Exception("Cannot set socket from systemd");
+ }
-AskUserTalker::AskUserTalker(GuiRunner *gui) : m_clientSocket(Socket::PeerType::CLIENT), m_gui(gui) {
- m_gui->setDropHandler([&](){return this->shouldDismiss();});
+ int ret = sd_notify(0, "READY=1");
+ if (ret == 0) {
+ ALOGW("Agent was not configured to notify its status");
+ } else if (ret < 0) {
+ ALOGE("sd_notify failed: [" << ret << "]");
+ }
+#else
+ m_serverSocket.bindAndListen(Path::getUserSocketPath(getuid()));
+#endif
+ m_poller.setEvents(m_serverSocket.getFd(), POLLIN);
+ setSignalDescriptor();
+ m_gui.initialize();
+ ALOGD("Initialized");
}
bool AskUserTalker::fetchRequest(NotificationRequest &request) {
std::string requestData;
- if (!m_clientSocket.recv(requestData)) {
+ if (!m_currentPeerSocket.recv(requestData)) {
ALOGI("Failed fetching request, closing...");
return false;
}
}
bool AskUserTalker::sendResponse(const NotificationResponse &response) {
- if (!m_clientSocket.send(static_cast<int>(response.id))) {
+ if (!m_currentPeerSocket.send(static_cast<int>(response.id))) {
ALOGI("Askuserd closed connection, closing...");
return false;
}
- if (!m_clientSocket.send(static_cast<int>(response.response))) {
+ if (!m_currentPeerSocket.send(static_cast<int>(response.response))) {
ALOGI("Askuserd closed connection, closing...");
return false;
}
return true;
}
-void AskUserTalker::run()
-{
- m_clientSocket.connect(Path::getSocketPath());
+void AskUserTalker::handlePeer() {
+ NotificationRequest request;
+ if (!fetchRequest(request)) {
+ ALOGE("Couldn't fetch request, closing...");
+ return;
+ }
- while (!stopFlag) {
- ALOGD("Waiting for request...");
- NotificationRequest request;
- if (!fetchRequest(request)) {
- ALOGE("Couldn't fetch request, closing...");
- break;
- }
+ m_gui.addDismissFd(m_currentPeerSocket.getFd(), AskUserTalker::dissmissCb, this);
- NotificationResponse response;
- response.response = m_gui->popupRun(request.data.client,
- PrivilegeInfo::getPrivilegeDisplayName(request.data.privilege));
- response.id = request.id;
+ NotificationResponse response;
+ response.response = m_gui.popupRun(request.data.client,
+ PrivilegeInfo::getPrivilegeDisplayName(request.data.privilege));
- if (response.response == NResponseType::None) {
- continue;
- }
+ m_gui.delDismissFd(m_currentPeerSocket.getFd());
- if (!sendResponse(response)) {
- ALOGE("Couldn't send response, closing...");
- break;
- }
+ response.id = request.id;
+ if (response.response == NResponseType::None) {
+ return;
+ }
- int ack = 0;
- if (!m_clientSocket.recv(ack)) {
- ALOGI("Askuserd closed connection, closing...");
- break;
- }
+ if (!sendResponse(response)) {
+ ALOGE("Couldn't send response, closing...");
+ return;
+ }
+
+ switch (response.response) {
+ case NResponseType::Error:
+ ALOGE("Error in user interface : " << m_gui.getErrorMsg());
+ break;
+ case NResponseType::Allow:
+ case NResponseType::Never:
+ setSecurityLevel(request.data.client, request.data.privilege,
+ Translator::Gui::responseToString(response.response));
+ break;
+ case NResponseType::Deny:
+ case NResponseType::None:
+ break;
+ default:
+ ALOGW("Unknown response type returned");
+ break;
+ }
- if (ack != Protocol::ackCode)
- throw Exception("Incorrect ack");
+ return;
+}
- switch (response.response) {
- case NResponseType::Error:
- throw Exception(m_gui->getErrorMsg());
- case NResponseType::Allow:
- case NResponseType::Never:
- setSecurityLevel(request.data.client, request.data.privilege,
- Translator::Gui::responseToString(response.response));
- break;
- default:
- ALOGD("Unknown response type returned");
- break;
- }
+void AskUserTalker::activateCurrentClient() {
+ ALOGD("Activating current peer : " << m_currentPeerSocket.getFd());
+ m_poller.setEvents(m_currentPeerSocket.getFd(), POLLIN | POLLHUP | POLLERR);
+}
+void AskUserTalker::deactivateCurrentClient() {
+ ALOGD("Deactivating current peer : " << m_currentPeerSocket.getFd());
+ m_poller.unset(m_currentPeerSocket.getFd());
+}
+
+void AskUserTalker::switchToNextClient() {
+ deactivateCurrentClient();
+ m_currentPeerSocket.close();
+ if (m_pendingPeers.empty()) {
+ ALOGD("No pending peers");
+ return;
}
+ m_currentPeerSocket = std::move(m_pendingPeers.front());
+ m_pendingPeers.pop_front();
+ activateCurrentClient();
+ ALOGD("Setting current peer : " << m_currentPeerSocket.getFd());
}
-void AskUserTalker::stop()
-{
- m_gui->stop();
- m_clientSocket.close();
+void AskUserTalker::addNewClient(Socket &&newPeer) {
+ if (m_currentPeerSocket.getFd() == -1) {
+ ALOGD("Setting current peer : " << newPeer.getFd());
+ m_currentPeerSocket = std::move(newPeer);
+ activateCurrentClient();
+ } else {
+ m_pendingPeers.emplace_back(std::move(newPeer));
+ ALOGD("Pushing peer to queue : " << newPeer.getFd());
+ }
}
-bool AskUserTalker::shouldDismiss()
+void AskUserTalker::run()
{
- Poll poller(1);
- poller.setEvents(sockfd, POLLIN);
- int ret = poller.wait(0);
- if (ret == 0)
- return false;
- if (ret == -1) {
- ALOGE("Poll failed");
- return true;
- }
- int a = 0x00;
- m_clientSocket.recv(a);
+ m_running = true;
+ m_gui.addDismissFd(m_signalSocket.getFd(), AskUserTalker::dissmissCb, this);
+ while(m_running) {
+ int ret = m_poller.wait(-1);
+ if (ret == -1) {
+ ALOGE_ERRNO("Poll failed: ");
+ break;
+ }
+ if (ret == 0) {
+ ALOGD("Strange, poll timeouted...");
+ continue;
+ }
- if (a != Protocol::dissmisCode)
- throw Exception("Incorrect dismiss flag");
+ ALOGD("Poll returned " << ret << " events");
+ // signal fd
+ if (m_poller.getEvents(m_signalSocket.getFd()) & POLLIN) {
+ signalfd_siginfo si;
+ if (!m_signalSocket.recv(si)) {
+ ALOGE_ERRNO("Reading signal info failed");
+ break;
+ }
+ if (si.ssi_signo == SIGTERM) {
+ ALOGD("Got signal to exit, closing...");
+ break;
+ } else {
+ ALOGW("Unknown signal caught, ignoring...");
+ }
+ }
+ // listen fd
+ if (m_poller.getEvents(m_serverSocket.getFd()) & POLLIN) {
+ ALOGD("New peer connected");
+ Socket newPeer = std::move(m_serverSocket.accept());
+ if (newPeer.getFd() == -1) {
+ throw ErrnoException("Failed to accept new peer");
+ }
+
+ addNewClient(std::move(newPeer));
+ continue;
+ }
+ // client fd
+ if ((m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLHUP)
+ || (m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLERR)) {
+ LOGW("Peer disconnected or error");
+ switchToNextClient();
+ continue;
+ }
+ if (m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLIN) {
+ // Handle client then switch to next accepted client
+ ALOGD("Fetching request from client");
+ handlePeer();
+ switchToNextClient();
+ }
+ }
+ m_running = false;
+ stop();
+}
- return true;
+void AskUserTalker::stop()
+{
+ m_gui.delDismissFd(m_currentPeerSocket.getFd());
+ m_gui.delDismissFd(m_signalSocket.getFd());
+ m_gui.stop();
+ m_currentPeerSocket.close();
+ for (auto &peer: m_pendingPeers) {
+ peer.close();
+ }
+ m_serverSocket.close();
}
} /* namespace Notification */
* limitations under the License
*/
/**
- * @file src/notification-daemon/GuiRunner.h
+ * @file src/agent/notification-daemon/AskUserTalker.h
* @author Oskar Świtalski <o.switalski@samsung.com>
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
* @brief Declaration of AskUserTalker class
*/
#pragma once
+#include <list>
#include "GuiRunner.h"
+#include <socket/Poll.h>
#include <socket/Socket.h>
#include <types/NotificationRequest.h>
#include <types/NotificationResponse.h>
class AskUserTalker
{
public:
- AskUserTalker(GuiRunner *gui);
+ AskUserTalker();
+ void init();
void run();
void stop();
- bool shouldDismiss();
-
private:
+ static void dissmissCb(int fd, void *data);
+ void setSignalDescriptor();
+ void activateCurrentClient();
+ void deactivateCurrentClient();
+ void addNewClient(Socket &&newPeer);
+ void switchToNextClient();
+ void handlePeer();
bool fetchRequest(NotificationRequest &request);
bool sendResponse(const NotificationResponse &response);
- Socket m_clientSocket;
- GuiRunner *m_gui;
- int sockfd = 0;
- bool stopFlag = false;
+ Poll m_poller;
+ Socket m_signalSocket;
+ Socket m_serverSocket;
+ Socket m_currentPeerSocket;
+ GuiRunner m_gui;
+ std::list<Socket> m_pendingPeers;
+ bool m_dismissPopup = false;
+ bool m_running = false;
};
} /* namespace Notification */
* limitations under the License
*/
/**
- * @file src/notification-daemon/GuiRunner.cpp
+ * @file src/agent/notification-daemon/GuiRunner.cpp
* @author Oskar Świtalski <o.switalski@samsung.com>
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
* @brief Definition of GuiRunner class
*/
namespace Notification {
-namespace {
-
-bool should_raise = false;
-
-void unfocused(void *data, Evas_Object *, void *)
+void GuiRunner::unfocused(void *data, Evas_Object *, void *)
{
- if (data == NULL)
- return;
+ GuiRunner *runner = static_cast<GuiRunner*>(data);
- PopupData *res = static_cast<PopupData*>(data);
-
- if (should_raise)
- elm_win_raise(res->win);
+ if (runner->m_shouldRaise)
+ elm_win_raise(runner->m_win);
else
elm_exit();
}
-void inline win_close(Evas_Object *win) {
- should_raise = false;
- elm_win_lower(win);
+void GuiRunner::winClose()
+{
+ ALOGD("Window close");
+ m_shouldRaise = false;
+ elm_win_lower(m_win);
}
-void inline answer(void *data, NResponseType response)
+void GuiRunner::answer(NResponseType response)
{
ALOGD("User selected: " + Translator::Gui::responseToString(response));
- if (data == NULL)
- return;
-
- PopupData *res = static_cast<PopupData*>(data);
- res->type = response;
- win_close(res->win);
+ m_popupResponse = response;
+ winClose();
}
-void allow_answer(void *data, Evas_Object *, void *)
+void GuiRunner::allowAnswerCb(void *data, Evas_Object *, void *)
{
- answer(data, NResponseType::Allow);
+ GuiRunner* runner = static_cast<GuiRunner*>(data);
+ runner->answer(NResponseType::Allow);
}
-void deny_answer(void *data, Evas_Object *, void *)
+void GuiRunner::denyAnswerCb(void *data, Evas_Object *, void *)
{
- answer(data, NResponseType::Deny);
+ GuiRunner* runner = static_cast<GuiRunner*>(data);
+ runner->answer(NResponseType::Deny);
}
-void never_answer(void *data, Evas_Object *, void *)
+void GuiRunner::neverAnswerCb(void *data, Evas_Object *, void *)
{
- answer(data, NResponseType::Never);
+ GuiRunner* runner = static_cast<GuiRunner*>(data);
+ runner->answer(NResponseType::Never);
}
-Eina_Bool timeout_answer(void *data) {
- if (!data)
- return ECORE_CALLBACK_RENEW;
+Eina_Bool GuiRunner::dismissFdCb(void *data, Ecore_Fd_Handler *handler) {
+ ALOGD("Dismiss fd awoken");
+ GuiRunner *runner = static_cast<GuiRunner*>(data);
- drop *d = static_cast<drop*>(data);
-
- if (d->handle()) {
- win_close(d->popup->win);
+ int fd = ecore_main_fd_handler_fd_get(handler);
+ if (fd == -1) {
+ ALOGE("Failed to fetch fd from handler");
+ return ECORE_CALLBACK_CANCEL;
}
- return ECORE_CALLBACK_RENEW;
+ ALOGD("Dismiss descriptor " << fd << " is active, closing window...");
+ auto fdIt = runner->m_fdCbDataMap.find(fd);
+ if (fdIt == runner->m_fdCbDataMap.end())
+ return ECORE_CALLBACK_CANCEL;
+
+ auto cbData = fdIt->second;
+ cbData.userCb(fd, cbData.userData);
+ runner->m_fdCbDataMap.erase(fdIt);
+
+ runner->winClose();
+ return ECORE_CALLBACK_CANCEL;
}
-} /* namespace */
+GuiRunner::~GuiRunner()
+{
+ for (auto &fdCbData : m_fdCbDataMap) {
+ ecore_main_fd_handler_del(fdCbData.second.handler);
+ }
+}
-GuiRunner::GuiRunner()
+void GuiRunner::delDismissFd(int fd)
{
- m_popupData = new PopupData({NResponseType::Deny, nullptr});
+ auto fdIt = m_fdCbDataMap.find(fd);
+ if (fdIt == m_fdCbDataMap.end())
+ return;
+ ecore_main_fd_handler_del(fdIt->second.handler);
+ m_fdCbDataMap.erase(fdIt);
}
-GuiRunner::~GuiRunner()
+void GuiRunner::addDismissFd(int fd, DissmissCb cb, void *data)
{
- delete m_popupData;
+ delDismissFd(fd);
+
+ auto handler = ecore_main_fd_handler_add(fd,
+ // Thank you efl for this ugly code
+ static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
+ &GuiRunner::dismissFdCb, this,
+ nullptr, nullptr);
+ if (handler == nullptr) {
+ throw Exception("Couldn't set fd handler");
+ }
+
+ m_fdCbDataMap[fd] = CbData{cb, data, handler};
}
void GuiRunner::initialize()
//placeholder
m_win = elm_win_add(NULL, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_TITLE"),
- ELM_WIN_DOCK);
+ ELM_WIN_DOCK);
+ if (!m_win) {
+ ALOGE("EFL : Failed to add window");
+ throw Exception("Elementary failed");
+ }
elm_win_autodel_set(m_win, EINA_TRUE);
elm_win_override_set(m_win, EINA_TRUE);
elm_win_alpha_set(m_win, EINA_TRUE);
// popup
m_popup = elm_popup_add(m_win);
+ if (!m_popup) {
+ ALOGE("EFL : Failed to add popup");
+ throw Exception("Elementary failed");
+ }
elm_object_part_text_set(m_popup, "title,text", dgettext(PROJECT_NAME,
"SID_PRIVILEGE_REQUEST_DIALOG_TITLE"));
// box
m_box = elm_box_add(m_popup);
+ if (!m_box) {
+ ALOGE("EFL : Failed to add box");
+ throw Exception("Enlightement failed");
+ }
evas_object_size_hint_weight_set(m_box, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(m_box, EVAS_HINT_FILL, 0.0);
// content
m_content = elm_label_add(m_popup);
+ if (!m_content) {
+ ALOGE("EFL : Failed to add content");
+ throw Exception("Enlightement failed");
+ }
elm_object_style_set(m_content, "elm.swallow.content");
elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED);
evas_object_size_hint_weight_set(m_content, EVAS_HINT_EXPAND, 0.0);
// buttons
m_allowButton = elm_button_add(m_popup);
+ if (!m_allowButton) {
+ ALOGE("EFL : Failed to add allow button");
+ throw Exception("Enlightement failed");
+ }
elm_object_part_content_set(m_popup, "button1", m_allowButton);
elm_object_text_set(m_allowButton, dgettext(PROJECT_NAME,
"SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_ALLOW"));
m_neverButton = elm_button_add(m_popup);
+ if (!m_neverButton) {
+ ALOGE("EFL : Failed to add never button");
+ throw Exception("Enlightement failed");
+ }
elm_object_text_set(m_neverButton, dgettext(PROJECT_NAME,
"SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_NEVER"));
elm_object_part_content_set(m_popup, "button2", m_neverButton);
m_denyButton = elm_button_add(m_popup);
+ if (!m_denyButton) {
+ ALOGE("EFL : Failed to add deny button");
+ throw Exception("Enlightement failed");
+ }
elm_object_text_set(m_denyButton, dgettext(PROJECT_NAME,
"SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_DENY"));
elm_object_part_content_set(m_popup, "button3", m_denyButton);
// callbacks
- evas_object_smart_callback_add(m_win, "unfocused", unfocused, m_popupData);
- evas_object_smart_callback_add(m_allowButton, "clicked", allow_answer, m_popupData);
- evas_object_smart_callback_add(m_neverButton, "clicked", never_answer, m_popupData);
- evas_object_smart_callback_add(m_denyButton, "clicked", deny_answer, m_popupData);
+ evas_object_smart_callback_add(m_win, "unfocused", &GuiRunner::unfocused, this);
+ evas_object_smart_callback_add(m_allowButton, "clicked", &GuiRunner::allowAnswerCb, this);
+ evas_object_smart_callback_add(m_neverButton, "clicked", &GuiRunner::neverAnswerCb, this);
+ evas_object_smart_callback_add(m_denyButton, "clicked", &GuiRunner::denyAnswerCb, this);
- m_popupData->win = m_win;
m_initialized = true;
-
}
NResponseType GuiRunner::popupRun(const std::string &app, const std::string &perm)
{
-
try {
- if (!m_dropHandler)
- throw Exception("DropHandler was not initialized");
-
- if (!m_initialized)
+ if (!m_initialized) {
initialize();
-
+ }
m_running = true;
- std::unique_ptr<drop> Drop(new drop({m_dropHandler, m_popupData}));
- m_timer = ecore_timer_add(0.1, timeout_answer, Drop.get());
// create message
char *messageFormat = dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_MESSAGE");
if (ret < 0)
throw ErrnoException("snprintf failed", errno);
- m_popupData->type = NResponseType::None;
+ m_popupResponse = NResponseType::None;
- should_raise = true;
+ m_shouldRaise = true;
elm_object_text_set(m_content, buf);
evas_object_show(m_win);
elm_win_raise(m_win);
+
+ ALOGD("Showing popup");
elm_run();
+ ALOGD("Popup closed");
- ecore_timer_del(m_timer);
m_running = false;
- should_raise = false;
+ m_shouldRaise = false;
} catch (const std::exception &e) {
- m_popupData->type = NResponseType::Error;
+ m_popupResponse = NResponseType::Error;
m_errorMsg = std::move(e.what());
}
- return m_popupData->type;
-}
-
-void GuiRunner::setDropHandler(DropHandler dropHandler)
-{
- m_dropHandler = dropHandler;
+ return m_popupResponse;
}
void GuiRunner::stop()
{
- if (m_running) {
- evas_object_hide(m_win);
- elm_exit();
- }
- elm_shutdown();
}
} /* namespace Notification */
* limitations under the License
*/
/**
- * @file src/notification-daemon/GuiRunner.h
+ * @file src/agent/notification-daemon/GuiRunner.h
* @author Oskar Świtalski <o.switalski@samsung.com>
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
* @brief Declaration of GuiRunner class
*/
#include <Elementary.h>
#include <functional>
+#include <map>
#include <string>
#include <types/NotificationResponse.h>
namespace Notification {
-typedef std::function<bool()> DropHandler;
-
-struct PopupData {
- NResponseType type;
- Evas_Object *win;
-};
-
-struct drop {
- DropHandler handle;
- PopupData *popup;
-};
-
class GuiRunner {
public:
- GuiRunner();
+ typedef std::function<void(int, void*)> DissmissCb;
+
+ GuiRunner() = default;
+ void initialize();
+ void addDismissFd(int fd, DissmissCb cb, void *data);
+ void delDismissFd(int fd);
~GuiRunner();
NResponseType popupRun(const std::string &app, const std::string &perm);
-
- void setDropHandler(DropHandler dropHandler);
void stop();
std::string getErrorMsg() { return m_errorMsg; }
private:
- PopupData *m_popupData;
- DropHandler m_dropHandler;
-
- Evas_Object *m_win;
- Evas_Object *m_popup;
- Evas_Object *m_box;
- Evas_Object *m_content;
- Evas_Object *m_allowButton;
- Evas_Object *m_neverButton;
- Evas_Object *m_denyButton;
- Ecore_Timer *m_timer;
+ static Eina_Bool dismissFdCb(void *data, Ecore_Fd_Handler *handler);
+ static void unfocused(void *data, Evas_Object *, void *);
+ static void allowAnswerCb(void *data, Evas_Object *, void *);
+ static void denyAnswerCb(void *data, Evas_Object *, void *);
+ static void neverAnswerCb(void *data, Evas_Object *, void *);
+
+ void answer(NResponseType response);
+ void winClose();
+
+ struct CbData {
+ DissmissCb userCb;
+ void *userData;
+ Ecore_Fd_Handler *handler;
+ };
+
+ std::map<int, CbData> m_fdCbDataMap;
+ NResponseType m_popupResponse = NResponseType::Error;
+
+ Evas_Object *m_win = nullptr;
+ Evas_Object *m_popup = nullptr;
+ Evas_Object *m_box = nullptr;
+ Evas_Object *m_content = nullptr;
+ Evas_Object *m_allowButton = nullptr;
+ Evas_Object *m_neverButton = nullptr;
+ Evas_Object *m_denyButton = nullptr;
bool m_running = false;
bool m_initialized = false;
+ bool m_shouldRaise = false;
std::string m_errorMsg;
-
- void initialize();
};
} /* namespace Notification */
try {
GuiRunner gui;
AskUserTalker askUserTalker(&gui);
+// AskUserTalker askUserTalker;
+ askUserTalker.init();
#ifdef BUILD_WITH_SYSTEMD_DAEMON
int ret = sd_notify(0, "READY=1");
#endif
askUserTalker.run();
-
} catch (std::exception &e) {
ALOGE("Askuser-notification stopped because of: <" << e.what() << ">.");
} catch (...) {
return *this;
}
+void Socket::setFd(int fd) {
+ // Setting fd can only happen for non initialized sockets
+ if ( m_fd != -1) {
+ ALOGW("Socket already initialized");
+ return;
+ }
+ m_fd = fd;
+}
+
bool Socket::connect(const std::string &path) {
+ if (m_fd != -1) {
+ ALOGW("Socket already initialized");
+ return false;
+ }
+
if (m_type != PeerType::CLIENT) {
ALOGW("Connect is available only for CLIENT type socket");
return false;
}
bool Socket::bindAndListen(const std::string &path) {
+ if (m_fd != -1) {
+ ALOGW("Socket already initialized");
+ return false;
+ }
+
if (m_type != PeerType::SERVER) {
ALOGW("Connect is available only for SERVER type socket");
return false;
int retFd = TEMP_FAILURE_RETRY(::accept(m_fd, nullptr, nullptr));
if (retFd < 0) {
ALOGE_ERRNO("accept failed");
- return -1;
+ return Socket(-1);
}
ALOGD("Accepted socket <" << retFd << ">");
return Socket(retFd);
return true;
}
+bool Socket::recv(signalfd_siginfo &info) {
+ struct signalfd_siginfo si;
+
+ if (!recvData(&si, sizeof(si))) {
+ return false;
+ }
+ info = si;
+ return true;
+}
+
bool Socket::sendData(const void *data, size_t len) {
+ if (m_type == PeerType::SIGNAL) {
+ ALOGW("Illegal usage of signal type socket");
+ return false;
+ }
int result = 0;
size_t bytesSend = 0;
void Socket::close() {
::close(m_fd);
+ m_fd = -1;
}
} /* namespace AskUser */
#include <string>
#include <unistd.h>
+#include <sys/signalfd.h>
namespace AskUser {
enum PeerType {
CLIENT, // connect
SERVER, // accept
- PEER // accepted peer
+ PEER, // accepted peer
+ SIGNAL // for signalfd
};
Socket(PeerType type) : m_type(type), m_fd(-1) {}
- Socket(int fd) : m_type(PEER), m_fd(fd) {}
+ Socket(int fd, PeerType type = PEER) : m_type(type), m_fd(fd) {}
Socket(const Socket &other) = delete;
Socket &operator=(const Socket &other) = delete;
~Socket() { ::close(m_fd); }
+ void setFd(int fd);
int getFd() const { return m_fd; }
bool connect(const std::string &path);
bool recv(std::string &msg);
bool recv(int &msg);
+ bool recv(signalfd_siginfo &info);
bool send(const std::string &msg);
bool send(int msg);