%if %{with_systemd_daemon}
mkdir -p %{buildroot}/%{_unitdir_user}/sockets.target.wants
ln -s ../askuser-notification-stream.socket %{buildroot}/%{_unitdir_user}/sockets.target.wants/askuser-notification-stream.socket
-ln -s ../askuser-notification-datagram.socket %{buildroot}/%{_unitdir_user}/sockets.target.wants/askuser-notification-datagram.socket
%endif
%post
%if %{with_systemd_daemon}
%{_unitdir_user}/askuser-notification.service
%{_unitdir_user}/askuser-notification-stream.socket
-%{_unitdir_user}/askuser-notification-datagram.socket
%{_unitdir_user}/sockets.target.wants/*
%endif
%{_datadir}/askuser-notification/res/*
namespace Notification {
-void Logic::addChannelFd(int fd, Ecore_Fd_Handler_Flags flags) {
+void Logic::addChannelFd(Protocol::ConnectionFd fd, const Protocol::Credentials &creds) {
+ // TODO check if doesn't already exist
+ // TODO translate to appId, pkgId and appIds from package
+ auto it = m_connToInfo.find(fd);
+ if (it != m_connToInfo.end()) {
+ ALOGE("Connection with fd : " << fd << " already exists. Closing connection");
+ m_clientChannel->process(fd, 0);
+ return;
+ }
+ (void)creds;
+ ConnectionInfo connInfo;
+ m_connToInfo.insert(it, std::make_pair(fd, connInfo));
+}
+
+void Logic::updateChannelFd(Protocol::ConnectionFd fd, Ecore_Fd_Handler_Flags flags) {
auto it = m_fdInfo.find(fd);
if (it != m_fdInfo.end()) {
m_fdInfo[fd].status = FdChange::CHANGE;
m_fdInfo[fd].status = FdChange::NONE;
}
-void Logic::removeChannelFd(int fd) {
+void Logic::removeChannelFd(Protocol::ConnectionFd fd) {
+ m_connToInfo.erase(fd);
auto it = m_fdInfo.find(fd);
if (it == m_fdInfo.end()) {
return;
processEvents();
}
+void Logic::popup(Protocol::ConnectionFd fd, Protocol::RequestId id, std::string &&privilege) {
+ (void)fd;
+ (void)id;
+ (void)privilege;
+}
+
bool Logic::isEventProcessed() {
return m_currentEventId != -1;
}
default:
clientResponse = -255; // error
}
- m_clientChannel->popupResponse(popupId, clientResponse);
+ // TODO create popup ids containing fd and request id
+ m_clientChannel->popupResponse(-1, popupId, clientResponse);
finishCurrentEvent();
processEvents();
}
void run();
void stop();
- void addChannelFd(int fd, Ecore_Fd_Handler_Flags flags);
- void removeChannelFd(int fd);
+ void addChannelFd(Protocol::ConnectionFd fd, const Protocol::Credentials &creds);
+ void updateChannelFd(Protocol::ConnectionFd fd, Ecore_Fd_Handler_Flags flags);
+ void removeChannelFd(Protocol::ConnectionFd fd);
void addEvent(IUIEvent *event);
+ void popup(Protocol::ConnectionFd fd, Protocol::RequestId id, std::string &&privilege);
~Logic() {}
private:
};
std::map<int, FdInfo> m_fdInfo;
+
+ struct ConnectionInfo {
+ std::string appId;
+ std::string pkgId;
+ std::vector<std::string> apps;
+ };
+
+ std::map<Protocol::ConnectionFd, ConnectionInfo> m_connToInfo;
};
} // namespace Notification
namespace AskUser {
namespace Protocol {
-void ServerCallbacks::updateFd(int fd, int mask) {
+void ServerCallbacks::newConnection(ConnectionFd fd, const Credentials &creds) {
+ m_service->addChannelFd(fd, creds);
+}
+
+void ServerCallbacks::updateConnection(ConnectionFd fd, int mask) {
if (mask == 0)
m_service->removeChannelFd(fd);
else
- m_service->addChannelFd(fd, maskToFlags(mask));
+ m_service->updateChannelFd(fd, maskToFlags(mask));
}
-void ServerCallbacks::popup_launch(int requestId, const std::string &pkgName,
- const std::string &appName, uid_t,
- const AskUser::Protocol::PrivilegeVector &privileges)
-{
- m_service->addEvent(new AskUser::Notification::EventPopupLaunch(m_popupper, requestId, appName, pkgName, privileges));
-}
-void ServerCallbacks::toast_deny(const std::string &pkgName, const std::string &appName,
- uid_t, const AskUser::Protocol::Privilege &privilege)
-{
- m_service->addEvent(new AskUser::Notification::EventToastDeny(m_popupper, 0, appName, pkgName, privilege));
-}
-void ServerCallbacks::toast_fail_launch(const std::string &pkgName, const std::string &appName,
- uid_t)
-{
- m_service->addEvent(new AskUser::Notification::EventToastFail(m_popupper, 0, appName, pkgName));
+void ServerCallbacks::popup(ConnectionFd fd, RequestId id, std::string &&privilege) {
+ m_service->popup(fd, id, std::move(privilege));
}
} /* namespace Notification */
ServerCallbacks(AskUser::Notification::Logic *logic, AskUser::Notification::Popupper *popupper)
: m_service(logic), m_popupper(popupper)
{}
- virtual void updateFd(int fd, int mask);
- virtual void popup_launch(int requestId, const std::string &pkgName,
- const std::string &appName, uid_t uid,
- const AskUser::Protocol::PrivilegeVector &privileges);
- virtual void toast_deny(const std::string &pkgName, const std::string &appName,
- uid_t uid, const AskUser::Protocol::Privilege &privilege);
- virtual void toast_fail_launch(const std::string &pkgName, const std::string &appName,
- uid_t uid);
+ virtual void newConnection(ConnectionFd fd, const Credentials &creds);
+ virtual void updateConnection(ConnectionFd fd, int mask);
+ virtual void popup(ConnectionFd fd, RequestId id, std::string &&privilege);
+
virtual ~ServerCallbacks() {}
private:
AskUser::Notification::Logic *m_service;
namespace AskUser {
namespace Protocol {
+typedef int ConnectionFd;
+typedef int RequestId;
+
enum FdMask {
READ = 1,
WRITE = 2,
};
+struct Credentials {
+ std::string label;
+ uid_t uid;
+};
+
/**
* IServiceCallbacks defines set of callbacks that must be implemented in service.
*/
virtual ~IServerCallbacks(){}
/**
+ * This function is called when new peer connection is established.
+ * Fd is file descriptor for this new peer connection.
+ *
+ * \param[in] fd Connection file descriptor
+ */
+ virtual void newConnection(ConnectionFd fd, const Credentials &creds) = 0;
+
+ /**
* This function gives you number of descriptor that should be watched by poll/select.
*
- * \param[in] fd Number of opened descriptor.
+ * \param[in] fd Connection file descriptor
* \param[in] mask Type of acction that is required on this descriptor.
* mask == 0 remove descriptor fd from watched pool
* mask == 1 watch descriptor for READ
* mask == 2 watch descriptor for WRITE
* maks == 3 watch descriptor for READ and WRITE
*/
- virtual void updateFd(int fd, int mask) = 0;
- /**
- * some client called popup function with parameters.
- */
- virtual void popup_launch(int requestId, const std::string &pkgName, const std::string &appName, uid_t uid, const PrivilegeVector &privileges) = 0;
- /**
- * some client called test_deny function with parameters.
- */
- virtual void toast_deny(const std::string &pkgName, const std::string &appName, uid_t uid, const Privilege &privilege) = 0;
+ virtual void updateConnection(ConnectionFd fd, int mask) = 0;
+
/**
- * some client called toast_fail_launch function with parameters.
+ * This function is called when popup request is received.
+ *
+ * \param[in] fd Connection file descriptor
+ * \param[in] id Request identifier
+ * \param[in] privilege Privilege for which permission is asked for
*/
- virtual void toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) = 0;
+ virtual void popup(ConnectionFd fd, RequestId id, std::string &&privilege) = 0;
};
struct IChannel {
virtual void process(int fd, int mask) = 0;
/**
- * Information about action that was choosed by user.
+ * Information about action that was chosen by user.
*
* \param[in] requestId Request number.
- * \param[in] response Information about action choosed by user.
+ * \param[in] response Information about action chosen by user.
*/
- virtual void popupResponse(int requestId, int response) = 0;
+ virtual void popupResponse(ConnectionFd fd, RequestId id, int response) = 0;
};
typedef std::unique_ptr<IChannel> ChannelPtr;
* @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
* @brief
*/
+
+#include <cstdlib>
#include <string>
+#include <sstream>
#include <askuser-notification/ask-user-service.h>
void Channel::init() {
Sock stream(Sock::SRV_STREAM);
- Sock datagram(Sock::SRV_DGRAM);
-
stream.connect(getStreamSocketPath(getuid()));
- datagram.connect(getDatagramSocketPath(getuid()));
-
- int fd1 = stream.getFd();
- int fd2 = datagram.getFd();
- m_socket[fd1] = SockDesc(std::move(stream));
- m_socket[fd2] = SockDesc(std::move(datagram));
+ int fd = stream.getFd();
+ m_sockets[fd] = SockDesc(std::move(stream));
- m_callbacks->updateFd(fd1, FdMask::READ);
- m_callbacks->updateFd(fd2, FdMask::READ);
+ m_callbacks->updateConnection(fd, FdMask::READ);
}
void Channel::parse(const std::string &data, std::vector<std::string> &parsedData)
void Channel::process(int fd, int mask) {
try {
- auto it = m_socket.find(fd);
- if (it == m_socket.end())
+ auto it = m_sockets.find(fd);
+ if (it == m_sockets.end())
return;
if (0 == mask) {
- m_callbacks->updateFd(fd, 0);
- m_socket.erase(it);
+ m_callbacks->updateConnection(fd, 0);
+ m_sockets.erase(it);
return;
}
int fd = client.getFd();
if (fd < 0)
return;
- m_socket[fd] = SockDesc(std::move(client));
- m_callbacks->updateFd(fd, FdMask::READ);
+ m_sockets[fd] = SockDesc(std::move(client));
+ m_callbacks->newConnection(fd, Credentials());
+ m_callbacks->updateConnection(fd, FdMask::READ);
return;
}
int ret = desc.sock.recv(desc.input);
if (ret <= 0) {
- m_callbacks->updateFd(fd, 0);
- m_socket.erase(fd);
+ m_callbacks->updateConnection(fd, 0);
+ m_sockets.erase(fd);
return;
}
desc.input.clear();
int command = std::stoi(params[0]);
- std::string &pkgName = params[1];
- std::string &appName = params[2];
- uid_t uid = std::stoi(params[3]);
+
switch (command) {
case MSGID_POPUP:
{
- PrivilegeVector vect(params.begin() + 4, params.end());
- m_callbacks->popup_launch(fd, pkgName, appName, uid, vect);
- break;
- }
- case MSGID_TOAST1:
- {
- std::string &privilege = params[4];
- m_callbacks->toast_deny(pkgName, appName, uid, privilege);
- break;
- }
- case MSGID_TOAST2:
- {
- m_callbacks->toast_fail_launch(pkgName, appName, uid);
+ std::string &privilege = params[1];
+ RequestId id = std::strtol(params[2].c_str(), nullptr, 10);
+ m_callbacks->popup(fd, id, std::move(privilege));
break;
}
+ default :
+ // TODO log the error
+ m_callbacks->updateConnection(fd, 0);
+ m_sockets.erase(fd);
}
}
int size = static_cast<int>(desc.output.size());
int result = desc.sock.send(desc.output);
if (result < 0) {
- m_callbacks->updateFd(fd, 0);
- m_socket.erase(fd);
+ m_callbacks->updateConnection(fd, 0);
+ m_sockets.erase(fd);
return;
}
if (result == size) {
desc.output.clear();
- m_callbacks->updateFd(fd, FdMask::READ);
+ m_callbacks->updateConnection(fd, FdMask::READ);
}
if (result < size) {
desc.output.erase(desc.output.begin(), desc.output.begin()+result);
}
}
- } catch (const std::exception &){}
+ } catch (const std::exception &){
+ // TODO handle error
+ }
}
-void Channel::popupResponse(int requestId, int response) {
+void Channel::popupResponse(ConnectionFd fd, RequestId id, int response) {
try {
- auto it = m_socket.find(requestId);
- if (it == m_socket.end())
+ auto it = m_sockets.find(fd);
+ if (it == m_sockets.end())
return;
auto &desc = it->second;
- std::string o = std::to_string(response);
+ std::stringstream ss;
+ ss << id << " " << response;
+ std::string o = ss.str();
std::copy(o.begin(), o.end(), std::back_inserter(desc.output));
- m_callbacks->updateFd(requestId, FdMask::READ | FdMask::WRITE);
+ m_callbacks->updateConnection(fd, FdMask::READ | FdMask::WRITE);
} catch (const std::exception &){}
}
Channel::~Channel() {
- for (auto &e : m_socket)
- m_callbacks->updateFd(e.first, 0);
+ for (auto &e : m_sockets)
+ m_callbacks->updateConnection(e.first, 0);
}
ChannelPtr createChannel(ServerCallbacksPtr ptr) {
{}
void init();
- virtual void process(int fd, int mask);
- virtual void popupResponse(int requestId, int response);
+ virtual void process(ConnectionFd fd, int mask);
+ virtual void popupResponse(ConnectionFd fd, RequestId id, int response);
virtual ~Channel();
private:
virtual void parse(const std::string &data, std::vector<std::string> &parsedData);
ServerCallbacksPtr m_callbacks;
- SocketMap m_socket;
+ SocketMap m_sockets;
};
} // namespace Protocol
struct Callbacks : public IServerCallbacks {
Callbacks() : m_channel(nullptr) {}
- virtual void updateFd(int fd, int mask) {
+ virtual void newConnection(ConnectionFd fd, const Credentials &creds) {
+ (void)fd;
+ (void)creds;
+ }
+ virtual void updateConnection(ConnectionFd fd, int mask) {
printf("call updateFd %d %d\n", fd, mask);
if (mask == 0) {
m_sockets.erase(fd);
m_sockets[fd] = mask;
}
- virtual void popup_launch(int requestId, const std::string &pkgName, const std::string &appName, uid_t uid, UNUSED const PrivilegeVector &priv) {
- printf("call popup %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
+ virtual void popup(ConnectionFd fd, RequestId id, Privilege &&priv) {
+ printf("call popup %s \n", priv.c_str());
if (m_channel)
- m_channel->popupResponse(requestId, 0xdeadbeef);
- }
-
- virtual void toast_deny(const std::string &pkgName, const std::string &appName, uid_t uid, UNUSED const Privilege &privilege) {
- printf("call toast_deny %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
- }
-
- virtual void toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) {
- printf("call toast_fail_launch %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
+ m_channel->popupResponse(fd, id, 0xdeadbeef);
}
void setChannel(IChannel *ptr) {
printf("Sended stream. Result: %x\n", result);
}
-void toust1() {
- toast_deny("org.tizen.memo", "org.tizen.memo", getuid(), "http://tizen.org/privilege/camera");
- printf("sended\n");
-}
-
-void toust2() {
- toast_fail_launch("org.tizen.memo", "org.tizen.memo", getuid());
- printf("sended\n");
-}
int main(){
int com;
case 1:
stream();
break;
- case 2:
- toust1();
- break;
- case 3:
- toust2();
- break;
}
return 0;
INSTALL(FILES
${CMAKE_SOURCE_DIR}/systemd/askuser-notification.service
${CMAKE_SOURCE_DIR}/systemd/askuser-notification-stream.socket
- ${CMAKE_SOURCE_DIR}/systemd/askuser-notification-datagram.socket
DESTINATION
lib/systemd/user
)
+++ /dev/null
-[Socket]
-ListenDatagram=/run/user_ext/%U/askuser-notification-datagram.socket
-SocketMode=0777
-
-Service=askuser-notification.service
-
-[Install]
-WantedBy=sockets.target