From 0ef5ca6d407c94af8d557c7c82ad6252717359ac Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Tue, 29 May 2018 07:19:28 +0200 Subject: [PATCH] Adjust server-side logic to use one popup with many privileges Change-Id: Ie15a6affd059f9b48457e35722812774da23bb8a --- src/notification-daemon/Logic.cpp | 131 ++++++++++++++---------------- src/notification-daemon/Logic.h | 22 ++--- src/notification-daemon/PolicyUpdater.cpp | 62 ++++++++------ src/notification-daemon/PolicyUpdater.h | 11 +-- src/notification-daemon/event/Event.h | 13 ++- src/notification-daemon/ui/Popupper.cpp | 6 +- src/notification-daemon/ui/Popupper.h | 3 +- 7 files changed, 123 insertions(+), 125 deletions(-) diff --git a/src/notification-daemon/Logic.cpp b/src/notification-daemon/Logic.cpp index 3e16add..f7b305b 100644 --- a/src/notification-daemon/Logic.cpp +++ b/src/notification-daemon/Logic.cpp @@ -209,26 +209,18 @@ Eina_Bool Logic::processChannel(int fd, int mask) { } void Logic::addEvent(Protocol::ConnectionFd fd, Protocol::RequestId id, - const std::map> &privsToAskablePrivacies, - const std::map &privsToPolicy, - const std::vector &privs, - const std::vector &privacies) { + const std::vector &privacies, + const std::vector &privilegesStructure) { EventId eventId{fd, id}; auto &ev = m_eventInfo[eventId]; - PrivaciesSequence &seq = ev.privaciesSeq; - seq.setPrivacies(privacies); - ev.privilegesAskablePrivacies = privsToAskablePrivacies; - ev.privilegesPolicy = privsToPolicy; - ev.privileges = privs; + ev.uniquePrivacies = privacies; + ev.privilegesStructure = privilegesStructure; ev.privacyResponses.clear(); ConnectionInfo &conn = m_connToInfo[fd]; - Privacy currentPrivacy; - seq.getNextPrivacy(currentPrivacy); - - FdEvent fdEvent{eventId, std::unique_ptr(new EventPopupCheck(&m_popupper, conn.pkgId, currentPrivacy))}; + FdEvent fdEvent{eventId, std::unique_ptr(new EventPopupCheck(&m_popupper, conn.pkgId, privacies))}; m_pendingEvents.emplace_back(std::move(fdEvent)); } @@ -245,25 +237,27 @@ void Logic::popup(Protocol::ConnectionFd fd, Protocol::RequestId id, const std:: } ConnectionInfo &conn = it->second; PkgMgrAppInfo appInfo; - std::map> privsToAskablePrivacies; - std::map privsToPolicy; std::set uniquePrivacies; + std::vector privilegesStructure; for (auto &privilege : privileges) { + PrivilegeStruct privStruct; + privStruct.privilege = privilege; PrivilegePolicy privPolicy(conn.appId, privilege); - privsToPolicy[privilege] = privPolicy.calculatePolicy(appInfo); - ALOGD("Privilege " << privilege << " policy level calculated to : " << privsToPolicy[privilege]); - if (privsToPolicy[privilege] == "Ask user") { - privsToAskablePrivacies[privilege] = privPolicy.calculateAskablePrivacies(appInfo); - if (privsToAskablePrivacies[privilege].empty()) { + privStruct.policy = privPolicy.calculatePolicy(appInfo); + ALOGD("Privilege " << privilege << " policy level calculated to : " << privStruct.policy); + if (privStruct.policy == "Ask user") { + privStruct.askablePrivacies = privPolicy.calculateAskablePrivacies(appInfo); + if (privStruct.askablePrivacies.empty()) { ALOGE("All privacies for privilege " << privilege << " are already allowed"); - privsToPolicy[privilege] = "Allow"; + privStruct.policy = "Allow"; } else { - for (auto &privacy : privsToAskablePrivacies[privilege]) + for (auto &privacy : privStruct.askablePrivacies) uniquePrivacies.insert(privacy); } } + privilegesStructure.push_back(std::move(privStruct)); } if (uniquePrivacies.empty()) { @@ -271,12 +265,12 @@ void Logic::popup(Protocol::ConnectionFd fd, Protocol::RequestId id, const std:: std::vector responses; responses.resize(privileges.size()); for (size_t i = 0; i < privileges.size(); ++i) { - if (privsToPolicy[privileges[i]] == "Allow") { + if (privilegesStructure[i].policy == "Allow") { responses[i] = ASKUSER_ALLOW_FOREVER; - } else if (privsToPolicy[privileges[i]] == "Deny") { + } else if (privilegesStructure[i].policy == "Deny") { responses[i] = ASKUSER_DENY_FOREVER; } else { - ALOGE("Unknown policy set : " << privsToPolicy[privileges[i]] << " for (" << conn.appId << ", " << conn.user + ALOGE("Unknown policy set : " << privilegesStructure[i].policy << " for (" << conn.appId << ", " << conn.user << ", " << privileges[i] << ")"); responses[i] = ASKUSER_DENY_ONCE; } @@ -287,7 +281,7 @@ void Logic::popup(Protocol::ConnectionFd fd, Protocol::RequestId id, const std:: // we do have privacies to ask about, we need to generate event std::vector privacies(uniquePrivacies.begin(), uniquePrivacies.end()); - addEvent(fd, id, privsToAskablePrivacies, privsToPolicy, privileges, privacies); + addEvent(fd, id, privacies, privilegesStructure); processEvents(); } catch (const std::exception &e) { @@ -406,7 +400,7 @@ void Logic::init() { init_agent_log(); m_popupper.initialize(); Po::setLocale(); - m_popupper.registerPopupResponseHandler([&](NResponseType response) { popupResponse(response);}); + m_popupper.registerPopupResponseHandler([&](std::vector responses) { popupResponses(responses);}); registerSignalFd(); @@ -421,24 +415,30 @@ void Logic::run() { bool Logic::setPolicy(const ConnectionInfo &conn) { ALOGD("Setting policy for app " << conn.appId); - for (auto &pr : m_eventInfo[m_currentEvent].privacyResponses) { - const auto &level = clientResponseToPolicy(pr.second); - if (!PolicyUpdater::update(conn.appId, pr.first, level)) { - ALOGE("Couldn't set policy for " << conn.appId << " privacy : " << pr.first << " level : " << level); - return false; - } + auto ¤tEvent = m_eventInfo[m_currentEvent]; + std::vector levels(currentEvent.uniquePrivacies.size()); + + for (size_t i = 0; i < levels.size(); ++i) { + const auto &privacy = currentEvent.uniquePrivacies[i]; + levels[i] = clientResponseToPolicy(currentEvent.privacyResponses[privacy]); } + + if (!PolicyUpdater::update(conn.appId, currentEvent.uniquePrivacies, levels)) { + ALOGE("Couldn't set policy for " << conn.appId); + return false; + } + return true; } void Logic::processResponse(const ConnectionInfo &conn) { auto ¤tEvent = m_eventInfo[m_currentEvent]; - std::vector responses(currentEvent.privileges.size(), ASKUSER_UNKNOWN_ERROR); + std::vector responses(currentEvent.privilegesStructure.size(), ASKUSER_UNKNOWN_ERROR); if (setPolicy(conn)) { for (size_t i = 0; i < responses.size(); ++i) { - const auto &privilege = currentEvent.privileges[i]; - const auto &policy = currentEvent.privilegesPolicy[privilege]; + const auto &privilegeStruct = currentEvent.privilegesStructure[i]; + const auto &policy = privilegeStruct.policy; if (policy == "Allow") { responses[i] = ASKUSER_ALLOW_FOREVER; } else if (policy == "Deny") { @@ -449,61 +449,52 @@ void Logic::processResponse(const ConnectionInfo &conn) { // Ask user policy - need to calcualte from existing responses to privacies // but only privacies askable for this privilege should be used! responses[i] = ASKUSER_ALLOW_FOREVER; - bool hasAnswer = false; - for (auto &privacy : currentEvent.privilegesAskablePrivacies[privilege]) { - const auto &privResponses = currentEvent.privacyResponses; - const auto privResponseIt = privResponses.find(privacy); - if (privResponseIt != privResponses.end()) { + for (auto &privacy : privilegeStruct.askablePrivacies) { + const auto &privResponseIt = currentEvent.privacyResponses.find(privacy); + if (privResponseIt != currentEvent.privacyResponses.end()) { responses[i] = std::min(privResponseIt->second, responses[i]); - hasAnswer = true; + } + else { + ALOGE("Unable to response for askable privacy: " << privacy); + responses[i] = ASKUSER_DENY_ONCE; + break; } } - if (!hasAnswer) - responses[i] = ASKUSER_DENY_ONCE; } } } m_serverChannel->popupResponses(m_currentEvent.fd, m_currentEvent.id, std::move(responses)); } -void Logic::popupResponse(NResponseType response) { +void Logic::popupResponses(const std::vector &responses) { auto it = m_connToInfo.find(m_currentEvent.fd); + if (it == m_connToInfo.end()) { ALOGE("Got response from inactive fd " << m_currentEvent.fd); return; } + ConnectionInfo &conn = it->second; - PrivaciesSequence &seq = m_eventInfo[m_currentEvent].privaciesSeq; - int clientResponse = uiResponseToClientResponse(response); + auto ¤tEvent = m_eventInfo[m_currentEvent]; - std::string justAnsweredPrivacy; - if (!seq.getCurrentPrivacy(justAnsweredPrivacy)) { - ALOGE("Received response for unknown privacy - this should not happen"); + if (responses.size() != currentEvent.uniquePrivacies.size()) { + ALOGE("Got invalid number of responses: " << responses.size() << " but expected: " + << currentEvent.uniquePrivacies.size()); finishCurrentRequest(); processEvents(); return; } - m_eventInfo[m_currentEvent].privacyResponses[justAnsweredPrivacy] = clientResponse; - if (clientResponse != ASKUSER_ALLOW_FOREVER && m_eventInfo[m_currentEvent].privileges.size() == 1) { - // request for only 1 privilege is being processed and at least 1 privacy is not allowed - // stop iteration over privacies, its pointless as the privilege is alraedy dissallowed - processResponse(conn); - finishCurrentRequest(); - } else { - // request for many privileges is being processed or one privilege but still needs to be processed - Privacy nextPrivacy; - if (seq.getNextPrivacy(nextPrivacy)) { - // More privacies to process - replace existing event with new privacy - FdEvent fdEvent{m_currentEvent, std::unique_ptr(new EventPopupCheck(&m_popupper, conn.pkgId, nextPrivacy))}; - m_pendingEvents[0] = std::move(fdEvent); - // don't call finishCurrentRequest here, because it will pop event, which we replaced - m_currentEvent = EventId(); - } else { - // No more privacies, request is ready for response - processResponse(conn); - finishCurrentRequest(); - } + + for (size_t i = 0; i < responses.size(); ++i) { + int clientResponse = uiResponseToClientResponse(responses[i]); + const auto &privacy = currentEvent.uniquePrivacies[i]; + ALOGD("Client response for privacy " << privacy << " is " << clientResponse); + currentEvent.privacyResponses[privacy] = clientResponse; } + + // No more privacies, since all are answered by one popup - request is ready for response + processResponse(conn); + finishCurrentRequest(); processEvents(); } diff --git a/src/notification-daemon/Logic.h b/src/notification-daemon/Logic.h index e05c405..5e4a10a 100644 --- a/src/notification-daemon/Logic.h +++ b/src/notification-daemon/Logic.h @@ -29,7 +29,6 @@ #include #include "event/Event.h" -#include "PrivaciesSequence.h" namespace AskUser { @@ -76,6 +75,12 @@ private: std::string user; }; + struct PrivilegeStruct { + Privilege privilege; + Policy policy; + std::vector askablePrivacies; + }; + //Initialization void registerSignalFd(); void prepareChannel(); @@ -88,10 +93,8 @@ private: //static Eina_Bool signalHandler(void *data, int type, void *event); void addEvent(Protocol::ConnectionFd fd, Protocol::RequestId id, - const std::map> &privsToAskablePrivacies, - const std::map &privsToPolicy, - const std::vector &privs, - const std::vector &privacies); + const std::vector &privacies, + const std::vector &privilegesStructure); Eina_Bool processChannel(int fd, int mask); bool identifyClient(const std::string &label, std::string &appId, std::string &pkgId); @@ -103,7 +106,7 @@ private: void startTimer(); void stopTimer(); - void popupResponse(NResponseType response); + void popupResponses(const std::vector &response); bool processError(EventId id, int error); bool setPolicy(const ConnectionInfo &conn); @@ -136,10 +139,9 @@ private: std::map m_connToInfo; struct EventInfo { - PrivaciesSequence privaciesSeq; - std::vector privileges; - std::map> privilegesAskablePrivacies; - std::map privilegesPolicy; + std::vector uniquePrivacies; // privacies placement order is important, + // UI will only send back responses, so then Logic has to map responses to privacies + std::vector privilegesStructure; std::map privacyResponses; }; diff --git a/src/notification-daemon/PolicyUpdater.cpp b/src/notification-daemon/PolicyUpdater.cpp index fdf2e15..c99ec05 100644 --- a/src/notification-daemon/PolicyUpdater.cpp +++ b/src/notification-daemon/PolicyUpdater.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2018 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. @@ -16,6 +16,7 @@ /** * @file PolicyUpdater.cpp * @author Zofia Abramowska + * @author Tomasz Swierczek * @brief This file implements class of policy updater */ @@ -33,37 +34,50 @@ namespace AskUser { namespace Notification { -bool PolicyUpdater::update(const std::string &appId, - const std::string &privacy, const std::string &level) +bool PolicyUpdater::update(const std::string &appId, const std::vector &privacies, + const std::vector &levels) { try { - ALOGD("Generating policy update for: app: " << appId << ", privacy: " << privacy - << ", user:" << geteuid() << ", level: " << level); + ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid() + << ", privacies num: " << privacies.size()); + + if (privacies.size() != levels.size() || levels.size() == 0) { + ALOGE("Policy update for invalid parameres"); + return false; + } static const std::string user = std::to_string(geteuid()); PolicyRequest req; - auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy); - if (privacyPrivs.empty()) { - ALOGE("Unable to get privacy privileges for privacy " << privacy); - throw Exception("Unable to get privacy privileges for privacy " + privacy); - } + for (size_t i = 0; i < privacies.size(); ++i) { + const auto &privacy = privacies[i]; + const auto &level = levels[i]; + + ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid() + << ", privacy " << privacy << ", level: " << level); + + auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy); + if (privacyPrivs.empty()) { + ALOGE("Unable to get privacy privileges for privacy " << privacy); + throw Exception("Unable to get privacy privileges for privacy " + privacy); + } - for (auto &priv : privacyPrivs) { - std::string currentPolicy = getPrivilegePolicy(appId, priv); - if (currentPolicy.empty()) { - ALOGD("Application didn't request privilege " << priv << ", skipping"); - continue; + for (auto &priv : privacyPrivs) { + std::string currentPolicy = getPrivilegePolicy(appId, priv); + if (currentPolicy.empty()) { + ALOGD("Application didn't request privilege " << priv << ", skipping"); + continue; + } + ALOGD("Adding policy entries for : app: " << appId << ", priv: " + << priv << ", user:" << user << ", level: " + << level); + PolicyEntry entry; + entry.setApp(appId); + entry.setUser(user); + entry.setPrivilege(priv); + entry.setLevel(level); + req.addEntry(std::move(entry)); } - ALOGD("Adding policy entries for : app: " << appId << ", priv: " - << priv << ", user:" << user << ", level: " - << level); - PolicyEntry entry; - entry.setApp(appId); - entry.setUser(user); - entry.setPrivilege(priv); - entry.setLevel(level); - req.addEntry(std::move(entry)); } req.updatePolicy(); diff --git a/src/notification-daemon/PolicyUpdater.h b/src/notification-daemon/PolicyUpdater.h index f821fe0..8cc72a9 100644 --- a/src/notification-daemon/PolicyUpdater.h +++ b/src/notification-daemon/PolicyUpdater.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016 - 2018 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. @@ -16,25 +16,22 @@ /** * @file PolicyUpdater.h * @author Zofia Abramowska + * @author Tomasz Swierczek * @brief This file declares class of policy updater */ #pragma once -#include -#include #include #include -#include -#include namespace AskUser { namespace Notification { namespace PolicyUpdater { - bool update(const std::string &appId, const std::string &privacy, - const std::string &level); + bool update(const std::string &appId, const std::vector &privacies, + const std::vector &levels); }; } // namespace Agent diff --git a/src/notification-daemon/event/Event.h b/src/notification-daemon/event/Event.h index 95e43a0..f0dbff0 100644 --- a/src/notification-daemon/event/Event.h +++ b/src/notification-daemon/event/Event.h @@ -41,19 +41,16 @@ protected: class EventPopupCheck : public IUIEvent { public: - EventPopupCheck(Popupper *popupper, const std::string &pkgId, const std::string &privacy) - : IUIEvent(popupper), m_pkgId(pkgId) - { - //TODO: change in final commit to m_privacy(privacy) - m_privacy.push_back(privacy); - } + EventPopupCheck(Popupper *popupper, const std::string &pkgId, const std::vector &privacies) + : IUIEvent(popupper), m_pkgId(pkgId), m_privacies(privacies) + {} virtual void process() { - m_popupper->popupCheck(m_pkgId, m_privacy); + m_popupper->popupCheck(m_pkgId, m_privacies); } private: std::string m_pkgId; - std::vector m_privacy; + std::vector m_privacies; }; } //namespace AskUser diff --git a/src/notification-daemon/ui/Popupper.cpp b/src/notification-daemon/ui/Popupper.cpp index d731cc6..0ce48ee 100644 --- a/src/notification-daemon/ui/Popupper.cpp +++ b/src/notification-daemon/ui/Popupper.cpp @@ -97,8 +97,7 @@ void Popupper::buttonAnswer(IAnswerable::Button button) { m_responses.push_back(answer); if (m_responses.size() == m_privaciesSequence.size()) { - //TODO: change to m_responses in final commit - m_popupResponseHandler(m_responses[0]); + m_popupResponseHandler(m_responses); return; } @@ -230,8 +229,7 @@ void Popupper::respondToRest(NResponseType response) m_responses.push_back(response); alreadyRespondedCount++; } - //TODO: CHANGE TO m_responses in final commit - m_popupResponseHandler(m_responses[0]); + m_popupResponseHandler(m_responses); } void Popupper::start() diff --git a/src/notification-daemon/ui/Popupper.h b/src/notification-daemon/ui/Popupper.h index d6bd959..f9cb337 100644 --- a/src/notification-daemon/ui/Popupper.h +++ b/src/notification-daemon/ui/Popupper.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -43,7 +42,7 @@ namespace Notification { class Popupper { public: - typedef std::function PopupHandler; + typedef std::function&)> PopupHandler; Popupper() = default; void initialize(); -- 2.7.4