namespace {
-int eventsToAskUserMask(int events)
+inline int eventsToAskUserMask(int events)
{
return ((events & ASKUSER_READ_EVENT) ? AskUser::Protocol::FdMask::READ : 0) |
((events & ASKUSER_WRITE_EVENT) ? AskUser::Protocol::FdMask::WRITE : 0);
}
-int askUserMaskToEvents(int mask)
+inline int askUserMaskToEvents(int mask)
{
return ((AskUser::Protocol::FdMask::READ & mask) ? ASKUSER_READ_EVENT : 0) |
((AskUser::Protocol::FdMask::WRITE & mask) ? ASKUSER_WRITE_EVENT : 0);
}
-askuser_popup_result responseToAskUserPopupResult(int response)
+inline askuser_popup_result responseToAskUserPopupResult(int response)
{
switch (response) {
case ASKUSER_ALLOW_FOREVER:
return ASKUSER_POPUP_RESULT_DENY_ONCE;
}
+inline askuser_call_cause deduceCauseFromResponse(int response)
+{
+ if (response == ASKUSER_UNKNOWN_ERROR) {
+ return ASKUSER_CALL_CAUSE_ERROR;
+ }
+
+ return ASKUSER_CALL_CAUSE_ANSWER;
+}
+
} // namespace
namespace AskUser {
ApiInterfaceImpl::~ApiInterfaceImpl()
{
- for (const auto &closure : m_callbacks) {
- closure.second(closure.first, askuser_call_cause::ASKUSER_CALL_CAUSE_FINALIZE,
- askuser_popup_result::ASKUSER_POPUP_RESULT_DENY_ONCE);
- }
+ respondToAllRequests(ASKUSER_CALL_CAUSE_FINALIZE, ASKUSER_POPUP_RESULT_DENY_ONCE);
- m_callbacks.clear();
m_channel.reset();
}
auto policies = fetch.fetchPolicy();
if (policies.size() != 1) {
- ALOGE("Unusual situation, there are " << policies.size() << " policies for (" << appId << ", " << geteuid() << ", " << privilege << ")");
+ ALOGE("Unusual situation, there are " << policies.size() <<
+ " policies for (" << appId << ", " << geteuid() << ", " << privilege << ")");
return ASKUSER_CHECK_RESULT_DENY;
}
RequestId ApiInterfaceImpl::popupRequest(const PopupCallbackClosure &closure,
const std::string &privilege)
{
- Client::RequestId id = static_cast<Client::RequestId>(m_channel->popupRequest(privilege));
+ RequestId id = static_cast<RequestId>(m_channel->popupRequest(privilege));
+
+ auto it = m_popupClosures.find(id);
+ if (it != m_popupClosures.end()) {
+ ALOGE("Popup closure exists for id: " << id <<
+ " privilege: " << it->second.privilege() << ", replacing");
+ popupResponse(id, ASKUSER_UNKNOWN_ERROR);
+ }
- auto it = m_callbacks.find(id);
- if (it != m_callbacks.end()) {
- it->second(it->first, ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
- m_callbacks.erase(it);
+ if (popupRequestInProgress(privilege)) {
+ ALOGE("Privilege " << closure.privilege() << " already exists in the pending privileges set");
}
- m_callbacks.insert({id, closure});
+ m_requestedPrivileges.insert(privilege);
+ m_popupClosures.insert({id, closure});
return id;
}
+bool ApiInterfaceImpl::popupRequestInProgress(const std::string &privilege) const
+{
+ return m_requestedPrivileges.find(privilege) != m_requestedPrivileges.end();
+}
+
void ApiInterfaceImpl::updateConnection(Protocol::ConnectionFd fd, int mask)
{
m_statusClosure(fd, askUserMaskToEvents(mask));
- // remove all pending events
+ // the connection is about to close, respond to all pending requests
if (mask == ASKUSER_EMPTY_EVENTS) {
- for (const auto &closure : m_callbacks) {
- closure.second(closure.first, ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
- }
-
- m_callbacks.clear();
+ respondToAllRequests(ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
}
}
void ApiInterfaceImpl::popupResponse(Protocol::RequestId id, int response)
{
- auto it = m_callbacks.find(id);
- if (it == m_callbacks.end()) {
+ auto it = m_popupClosures.find(id);
+ if (it == m_popupClosures.end()) {
+ ALOGE("Couldn't find popup callback closure for id: " << id);
return;
}
- askuser_call_cause cause = ASKUSER_CALL_CAUSE_ANSWER;
- if (response == ASKUSER_UNKNOWN_ERROR) {
- cause = ASKUSER_CALL_CAUSE_ERROR;
+ const auto &closure = it->second;
+ if (!popupRequestInProgress(closure.privilege())) {
+ ALOGE("Couldn't find privilege " << closure.privilege() << " in the pending privileges set");
}
+ askuser_call_cause cause = deduceCauseFromResponse(response);
askuser_popup_result res = responseToAskUserPopupResult(response);
- it->second(id, cause, res);
- m_callbacks.erase(it);
+
+ closure(id, cause, res);
+
+ m_requestedPrivileges.erase(closure.privilege());
+ m_popupClosures.erase(it);
+}
+
+void ApiInterfaceImpl::respondToAllRequests(askuser_call_cause cause, askuser_popup_result result)
+{
+ for (const auto &closure : m_popupClosures) {
+ closure.second(closure.first, cause, result);
+ }
+
+ m_requestedPrivileges.clear();
+ m_popupClosures.clear();
}
} // namespace Client