+++ /dev/null
-/*
- * Copyright (c) 2016-2017 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.
- * 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 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 <signal.h>
-#include <string>
-#include <sys/signalfd.h>
-
-#include <policy/PrivilegeInfo.h>
-#include <socket/Socket.h>
-#include <socket/Poll.h>
-#include <types/NotificationResponse.h>
-#include <types/NotificationRequest.h>
-#include <exception/ErrnoException.h>
-#include <exception/Exception.h>
-#include <translator/GuiTranslator.h>
-#include <config/Path.h>
-
-#ifdef BUILD_WITH_SYSTEMD_DAEMON
-#include <systemd/sd-daemon.h>
-#endif
-
-namespace AskUser {
-
-namespace Notification {
-
-namespace {
-
-} /* 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");
- }
-
- 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.setLocale();
- m_gui.initialize();
- ALOGD("Initialized");
-}
-
-bool AskUserTalker::fetchRequest(NotificationRequest &request) {
- std::string requestData;
-
- if (!m_currentPeerSocket.recv(requestData)) {
- ALOGI("Failed fetching request, closing...");
- return false;
- }
-
- request = Translator::Gui::dataToNotificationRequest(requestData);
- ALOGD("Recieved data, client: " << request.data.client <<
- " privilege: " << request.data.privilege);
-
- return true;
-}
-
-bool AskUserTalker::sendResponse(const NotificationResponse &response) {
- if (!m_currentPeerSocket.send(static_cast<int>(response.id))) {
- ALOGI("Askuserd closed connection, closing...");
- return false;
- }
- if (!m_currentPeerSocket.send(static_cast<int>(response.response))) {
- ALOGI("Askuserd closed connection, closing...");
- return false;
- }
- return true;
-}
-
-void AskUserTalker::handlePeer() {
- NotificationRequest request;
- if (!fetchRequest(request)) {
- ALOGE("Couldn't fetch request, closing...");
- return;
- }
-
- m_gui.addDismissFd(m_currentPeerSocket.getFd(), AskUserTalker::dissmissCb, this);
-
- NotificationResponse response;
- m_gui.setLocale();
- response.response = m_gui.popupRun(request.pkgLabel,
- PrivilegeInfo::getPrivacyDisplayName(request.data.privilege));
-
- m_gui.delDismissFd(m_currentPeerSocket.getFd());
-
- response.id = request.id;
- if (response.response == NResponseType::None) {
- return;
- }
-
- 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::AllowAlways:
- case NResponseType::DenyAlways:
- case NResponseType::Deny:
- case NResponseType::None:
- ALOGD("Sending response " << static_cast<int>(response.response));
- break;
- default:
- ALOGW("Unknown response type returned");
- break;
- }
- return;
-}
-
-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::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());
- }
-}
-
-void AskUserTalker::run()
-{
- 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("Poll timeouted...");
- break;
- }
-
- 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)) {
- ALOGW("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();
-}
-
-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 */
-
-} /* namespace AskUser */
+++ /dev/null
-/*
- * Copyright (c) 2016-2017 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.
- * 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 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
- */
-
-#include "GuiRunner.h"
-
-#include <exception/ErrnoException.h>
-#include <exception/Exception.h>
-#include <translator/GuiTranslator.h>
-#include <libintl.h>
-#include <vconf.h>
-#include <efl_util.h>
-#include <system_info.h>
-
-#include <unistd.h>
-#include <memory>
-
-namespace AskUser {
-
-namespace Notification {
-
-void GuiRunner::unfocused(void *data, Evas_Object *, void *)
-{
- ALOGD("Unfocused");
- GuiRunner *runner = static_cast<GuiRunner*>(data);
-
- if (runner->m_shouldRaise) {
- evas_object_show(runner->m_win);
- } else {
- for (auto &fdCbData : runner->m_fdCbDataMap) {
- ecore_main_fd_handler_del(fdCbData.second.handler);
- }
- ecore_main_loop_iterate();
- elm_exit();
- }
-
-}
-
-void GuiRunner::winClose()
-{
- ALOGD("Window close");
- m_shouldRaise = false;
- evas_object_hide(m_win);
-}
-
-// responseMap[allow][always]
-const NResponseType responseMap[2][2] = {
- { NResponseType::Deny, NResponseType::DenyAlways },
- { NResponseType::AllowAlways, NResponseType::AllowAlways }
-};
-
-void GuiRunner::answer(bool allow)
-{
- Eina_Bool always = EINA_FALSE;
-
- if (!m_hwKeyClicked)
- always = elm_check_state_get(m_checkbox);
- else
- m_hwKeyClicked = false;
-
- m_popupResponse = responseMap[allow][always];
-
- ALOGD("User selected: " + Translator::Gui::responseToString(m_popupResponse));
-
- winClose();
-}
-
-void GuiRunner::allowAnswerCb(void *data, Evas_Object *, void *)
-{
- GuiRunner* runner = static_cast<GuiRunner*>(data);
- runner->answer(true);
-}
-
-void GuiRunner::denyAnswerCb(void *data, Evas_Object *, void *)
-{
- GuiRunner* runner = static_cast<GuiRunner*>(data);
- runner->answer(false);
-}
-
-Eina_Bool GuiRunner::hwKeyClickedCb(void *data, int type, void *event)
-{
- Ecore_Event_Key *ev = (Ecore_Event_Key*)event;
- GuiRunner* runner = static_cast<GuiRunner*>(data);
- ALOGD("HW button pressed. type <" << type << "> pressed key is <" << ev->key << ">");
- runner->m_hwKeyClicked = true;
- if (!strcmp("XF86Home", ev->key) || !strcmp("XF86Back", ev->key)) {
- ALOGD("Close the window and respond as deny once.");
- runner->m_shouldRaise = false;
- runner->answer(false);
- }
- return EINA_TRUE;
-}
-
-Eina_Bool GuiRunner::dismissFdCb(void *data, Ecore_Fd_Handler *handler) {
- ALOGD("Dismiss fd awoken");
- GuiRunner *runner = static_cast<GuiRunner*>(data);
-
- int fd = ecore_main_fd_handler_fd_get(handler);
- if (fd == -1) {
- ALOGE("Failed to fetch fd from handler");
- return ECORE_CALLBACK_CANCEL;
- }
-
- 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;
-}
-
-GuiRunner::~GuiRunner()
-{
- for (auto &fdCbData : m_fdCbDataMap) {
- ecore_main_fd_handler_del(fdCbData.second.handler);
- }
-}
-
-void GuiRunner::delDismissFd(int fd)
-{
- auto fdIt = m_fdCbDataMap.find(fd);
- if (fdIt == m_fdCbDataMap.end())
- return;
- ecore_main_fd_handler_del(fdIt->second.handler);
- m_fdCbDataMap.erase(fdIt);
-}
-
-void GuiRunner::addDismissFd(int fd, DissmissCb cb, void *data)
-{
- 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()
-{
- char *popupTitle = dgettext(PROJECT_NAME, "IDS_IDLE_HEADER_PRIVACY_REQUEST");
- char *checkBoxText = dgettext(PROJECT_NAME, "IDS_ST_OPT_DONT_SHOW_AGAIN");
- elm_init(0, NULL);
-
- m_win = elm_win_add(NULL, popupTitle, ELM_WIN_NOTIFICATION);
- if (!m_win) {
- ALOGE("EFL : Failed to add window");
- throw Exception("Elementary failed");
- }
- efl_util_set_notification_window_level(m_win, EFL_UTIL_NOTIFICATION_LEVEL_TOP);
-
- if (elm_win_wm_rotation_supported_get(m_win)) {
- int rots[4] = { 0, 90, 180, 270 };
- elm_win_wm_rotation_available_rotations_set(m_win, (const int *)(&rots), 4);
- }
-
- elm_win_autodel_set(m_win, EINA_TRUE);
- elm_win_override_set(m_win, EINA_TRUE);
- elm_win_alpha_set(m_win, EINA_TRUE);
-
- char *profileName = nullptr;
- system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
- if (!profileName) {
- ALOGE("profileName is NULL");
- throw Exception("get profileName failed");
- }
- std::unique_ptr<char, decltype(free)*> profileNamePtr(profileName, free);
- if (*profileName != 'w' && *profileName != 'W') {
- // popup
- m_popup = elm_popup_add(m_win);
- if (!m_popup) {
- ALOGE("EFL : Failed to add popup");
- throw Exception("Elementary failed");
- }
- elm_popup_align_set(m_popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
- elm_object_part_text_set(m_popup, "title,text", popupTitle);
- evas_object_size_hint_weight_set(m_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-
- // layout
- m_layout = elm_layout_add(m_popup);
- elm_layout_file_set(m_layout, RES_DIR"/popup_custom.edj", "popup_checkview_layout_mobile");
- evas_object_size_hint_weight_set(m_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-
- // content
- m_content = elm_label_add(m_layout);
- if (!m_content) {
- ALOGE("EFL : Failed to add content");
- throw Exception("Enlightement failed");
- }
- elm_object_style_set(m_content, "popup/default");
- elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED);
- evas_object_size_hint_weight_set(m_content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- evas_object_size_hint_align_set(m_content, EVAS_HINT_FILL, EVAS_HINT_FILL);
- elm_object_part_content_set(m_layout, "elm.swallow.content", m_content);
-
- // checkbox
- m_checkbox = elm_check_add(m_layout);
- if (!m_checkbox) {
- ALOGE("EFL : Failed to add checkbox");
- throw Exception("Enlightement failed");
- }
- elm_object_part_content_set(m_layout, "elm.swallow.end", m_checkbox);
- elm_object_text_set(m_checkbox, checkBoxText);
- elm_check_state_set(m_checkbox, EINA_FALSE);
- evas_object_show(m_checkbox);
-
- // buttons
- m_denyButton = elm_button_add(m_popup);
- if (!m_denyButton) {
- ALOGE("EFL : Failed to add deny button");
- throw Exception("Enlightement failed");
- }
- elm_object_part_content_set(m_popup, "button1", m_denyButton);
- elm_object_text_set(m_denyButton, dgettext(PROJECT_NAME,
- "IDS_IDLE_BUTTON_DENY"));
-
- 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, "button2", m_allowButton);
- elm_object_text_set(m_allowButton, dgettext(PROJECT_NAME,
- "IDS_IDLE_BUTTON_ALLOW_ABB7"));
- elm_object_content_set(m_popup, m_layout);
- evas_object_show(m_popup);
-
- } else {
- Evas_Object *icon;
-
- m_popup = elm_popup_add(m_win);
- elm_object_style_set(m_popup, "circle");
-
- m_layout = elm_layout_add(m_popup);
- elm_layout_theme_set(m_layout, "layout", "popup", "content/circle/buttons2");
- elm_object_part_text_set(m_layout, "elm.text.title", popupTitle);
- elm_object_content_set(m_popup, m_layout);
-
- m_layoutInner = elm_layout_add(m_layout);
- elm_layout_file_set(m_layoutInner, RES_DIR"/popup_custom.edj", "popup_checkview_internal");
- evas_object_size_hint_weight_set(m_layoutInner, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- elm_object_part_content_set(m_layout, "elm.swallow.content", m_layoutInner);
-
- m_content = elm_label_add(m_layoutInner);
- elm_object_style_set(m_content, "popup/default");
- elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED);
- evas_object_size_hint_weight_set(m_content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- evas_object_size_hint_align_set(m_content, EVAS_HINT_FILL, EVAS_HINT_FILL);
- elm_object_part_content_set(m_layoutInner, "label", m_content);
-
-
- m_checkbox = elm_check_add(m_popup);
- elm_object_style_set(m_checkbox, "popup");
- elm_object_text_set(m_checkbox, checkBoxText);
- elm_check_state_set(m_checkbox, EINA_FALSE);
- evas_object_size_hint_align_set(m_checkbox, EVAS_HINT_FILL, 0.0);
- elm_object_part_content_set(m_layoutInner, "elm.swallow.end", m_checkbox);
- evas_object_show(m_checkbox);
-
- m_allowButton = elm_button_add(m_popup);
- elm_object_style_set(m_allowButton, "popup/circle/right");
- elm_object_part_content_set(m_popup, "button2", m_allowButton);
-
- icon = elm_image_add(m_allowButton);
- elm_image_file_set(icon, RES_DIR"/tw_ic_popup_btn_check.png", NULL);
- evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- elm_object_part_content_set(m_allowButton, "elm.swallow.content", icon);
- evas_object_show(icon);
-
- m_denyButton = elm_button_add(m_popup);
- elm_object_style_set(m_denyButton, "popup/circle/left");
- elm_object_part_content_set(m_popup, "button1", m_denyButton);
-
- icon = elm_image_add(m_denyButton);
- elm_image_file_set(icon, RES_DIR"/tw_ic_popup_btn_delete.png", NULL);
- elm_object_part_content_set(m_denyButton, "elm.swallow.content", icon);
- evas_object_show(icon);
-
- evas_object_show(m_popup);
- }
- // callbacks
- elm_win_indicator_opacity_set(m_win, ELM_WIN_INDICATOR_OPAQUE);
- elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_SHOW);
- 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_denyButton, "clicked", &GuiRunner::denyAnswerCb, this);
- elm_win_keygrab_set(m_win, "XF86Home", 0, 0, 0, ELM_WIN_KEYGRAB_SHARED);
- elm_win_keygrab_set(m_win, "XF86Back", 0, 0, 0, ELM_WIN_KEYGRAB_TOPMOST);
- ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, &GuiRunner::hwKeyClickedCb, this);
-
- m_initialized = true;
-}
-
-void GuiRunner::setLocale()
-{
- char *lang = vconf_get_str(VCONFKEY_LANGSET);
- if (lang)
- {
- elm_language_set(lang);
- free(lang);
- }
- else
- ALOGE("language_set failed.");
-}
-
-NResponseType GuiRunner::popupRun(const std::string &pkgLabel, const std::string &perm)
-{
- try {
- setLocale();
- initialize();
-
- m_running = true;
- m_hwKeyClicked = false;
-
- // create message
- char *messageFormat = dgettext(PROJECT_NAME, "IDS_IDLE_POP_ALLOW_P1SS_TO_ACCESS_YOUR_P2SS_Q");
- char buf[BUFSIZ];
- int ret = std::snprintf(buf, sizeof(buf), messageFormat,
- pkgLabel.c_str(),
- perm.c_str());
-
- if (ret < 0)
- throw ErrnoException("snprintf failed", errno);
-
- m_popupResponse = NResponseType::None;
-
- m_shouldRaise = true;
-
- elm_object_text_set(m_content, buf);
-
- evas_object_show(m_popup);
- evas_object_show(m_win);
-
- ALOGD("Showing popup");
- elm_run();
- ALOGD("Popup closed");
-
- m_running = false;
- m_shouldRaise = false;
- elm_win_keygrab_unset(m_win, "XF86Home", 0, 0);
- elm_win_keygrab_unset(m_win, "XF86Back", 0, 0);
-
- evas_object_del(m_win);
- m_win = nullptr;
- } catch (const std::exception &e) {
- m_popupResponse = NResponseType::Error;
- m_errorMsg = std::move(e.what());
- }
-
- return m_popupResponse;
-}
-
-void GuiRunner::stop()
-{
-
-}
-
-} /* namespace Notification */
-
-} /* namespace AskUser */