2 * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
18 * @file ApiInterfaceImpl.cpp
19 * @author Piotr Sawicki <p.sawicki2@partner.samsung.com>
20 * @author Zofia Grzelewska <z.abramowska@samsung.com>
21 * @brief The definition of ApiInterfaceImpl.
26 #include <sys/types.h>
29 #include <policy/Policy.h>
30 #include <policy/PrivilegePolicy.h>
31 #include <client-channel.h>
32 #include <common-types.h>
34 #include "ClientCallbacks.h"
35 #include "ApiInterfaceImpl.h"
39 inline int eventsToAskUserMask(int events)
41 return ((events & ASKUSER_READ_EVENT) ? AskUser::Protocol::FdMask::READ : 0) |
42 ((events & ASKUSER_WRITE_EVENT) ? AskUser::Protocol::FdMask::WRITE : 0);
45 inline int askUserMaskToEvents(int mask)
47 return ((AskUser::Protocol::FdMask::READ & mask) ? ASKUSER_READ_EVENT : 0) |
48 ((AskUser::Protocol::FdMask::WRITE & mask) ? ASKUSER_WRITE_EVENT : 0);
51 inline askuser_popup_result responseToAskUserPopupResult(int response)
54 case ASKUSER_ALLOW_FOREVER:
55 return ASKUSER_POPUP_RESULT_ALLOW_FOREVER;
56 case ASKUSER_DENY_FOREVER:
57 return ASKUSER_POPUP_RESULT_DENY_FOREVER;
58 case ASKUSER_DENY_ONCE:
59 return ASKUSER_POPUP_RESULT_DENY_ONCE;
62 return ASKUSER_POPUP_RESULT_DENY_ONCE;
65 inline askuser_call_cause deduceCauseFromResponse(int response)
67 if (response == ASKUSER_UNKNOWN_ERROR) {
68 return ASKUSER_CALL_CAUSE_ERROR;
71 return ASKUSER_CALL_CAUSE_ANSWER;
80 ApiInterfaceImpl::ApiInterfaceImpl(const StatusCallbackClosure &statusClosure)
81 : m_statusClosure(statusClosure)
83 Protocol::ClientCallbacksPtr callbacks(new ClientCallbacks(this));
84 std::unique_ptr<Protocol::ClientChannel> channel(new Protocol::ClientChannel(std::move(callbacks)));
85 m_channel = std::move(channel);
88 ApiInterfaceImpl::~ApiInterfaceImpl()
90 respondToAllRequests(ASKUSER_CALL_CAUSE_FINALIZE, ASKUSER_POPUP_RESULT_DENY_ONCE);
95 int ApiInterfaceImpl::process(int fd, int events)
97 return m_channel->process(fd, eventsToAskUserMask(events));
100 askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privilege)
102 std::string appId = getOwnAppId(m_pkgInfo);
103 PrivilegePolicy privPolicy(appId, privilege);
104 auto policyLevel = privPolicy.calculatePolicy(m_appInfo);
106 if (policyLevel == "Allow") {
107 return ASKUSER_CHECK_RESULT_ALLOW;
110 if (policyLevel == "Deny") {
111 return ASKUSER_CHECK_RESULT_DENY;
114 if (policyLevel == "Ask user") {
115 return ASKUSER_CHECK_RESULT_ASK;
118 ALOGE("Unknown policy level set : " << policyLevel <<
119 " for app " << appId << " and privilege " << privilege);
120 return ASKUSER_CHECK_RESULT_DENY;
123 RequestId ApiInterfaceImpl::popupRequest(const std::string &privilege,
124 const askuser_popup_response_callback callback,
127 Protocol::ConnectionContext conCtx = m_channel->popupRequest(privilege);
129 auto sameRequest = [&] (const Request &req) {
130 return req.m_requestId == conCtx.m_requestId;
133 auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameRequest);
134 if (reqIt != m_requests.end()) {
135 ALOGE("Popup closure exists for id: " << conCtx.m_requestId <<
136 " privilege: " << reqIt->m_privilege << ", replacing");
137 popupResponse(conCtx.m_requestId, ASKUSER_UNKNOWN_ERROR);
140 if (popupRequestInProgress(privilege)) {
141 ALOGE("Privilege " << privilege << " already exists in the pending requests");
144 m_requests.push_back({ conCtx.m_requestId, conCtx.m_fd, privilege, callback, userData });
146 return conCtx.m_requestId;
149 bool ApiInterfaceImpl::popupRequestInProgress(const std::string &privilege) const
151 auto samePrivilege = [&] (const Request &req) {
152 return req.m_privilege == privilege;
155 return std::find_if(m_requests.begin(), m_requests.end(), samePrivilege) != m_requests.end();
158 void ApiInterfaceImpl::updateConnection(Protocol::ConnectionFd fd, int mask)
160 m_statusClosure(fd, askUserMaskToEvents(mask));
162 if (mask == ASKUSER_EMPTY_EVENTS) {
163 auto sameFd = [&] (const Request &req) {
164 return req.m_fd == fd;
167 auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameFd);
168 if (reqIt == m_requests.end()) {
172 ALOGW("askuser-notification has been unexpectedly stopped, "
173 "sending the error response for privilege: "
174 << reqIt->m_privilege << " id: " << reqIt->m_requestId);
176 popupResponse(reqIt->m_requestId, ASKUSER_UNKNOWN_ERROR);
180 void ApiInterfaceImpl::popupResponse(Protocol::RequestId id, int response)
182 auto sameRequestId = [&] (const Request &req) {
183 return req.m_requestId == id;
186 auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameRequestId);
187 if (reqIt == m_requests.end()) {
188 ALOGE("Couldn't find request for id: " << id);
192 askuser_call_cause cause = deduceCauseFromResponse(response);
193 askuser_popup_result res = responseToAskUserPopupResult(response);
195 reqIt->m_callback(id, cause, res, reqIt->m_privilege.c_str(), reqIt->m_userData);
197 m_requests.erase(reqIt);
200 void ApiInterfaceImpl::respondToAllRequests(askuser_call_cause cause, askuser_popup_result result)
202 for (const auto &req : m_requests) {
203 req.m_callback(req.m_requestId, cause, result,
204 req.m_privilege.c_str(), req.m_userData);
210 } // namespace Client
212 } // namespace AskUser