From aa9c655b06ecb95622dde002878cff75c407370d Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Mon, 17 Jul 2017 11:36:36 +0200 Subject: [PATCH] Add 's' command to the CAPI test application From now on, the application has the 's' command which sends a pop-up request, in the same way as 'r' command does, but after receiving 'deny forever' response it stops the application. Also, the source code has been reorganised to achieve better readability. Change-Id: If2bb7fcee45489ac8246bdbf6703ab0f88fdf87c --- src/capi/test/privacy_privilege_manager_test.cpp | 586 ++++++++++++----------- 1 file changed, 297 insertions(+), 289 deletions(-) diff --git a/src/capi/test/privacy_privilege_manager_test.cpp b/src/capi/test/privacy_privilege_manager_test.cpp index 689b99b..e448c39 100644 --- a/src/capi/test/privacy_privilege_manager_test.cpp +++ b/src/capi/test/privacy_privilege_manager_test.cpp @@ -21,7 +21,6 @@ * @brief This file contains test of CAPI for Privacy Privilege Manager */ -#include #include #include #include @@ -63,6 +62,8 @@ typedef std::set PrivilegeRequestSet; struct ClientRequest { RequestId m_id; Privilege m_privilege; + GMainLoop *m_mainLoop; + bool m_stopAppAfterDeny; }; struct Connection @@ -82,8 +83,8 @@ const GIOCondition GIO_ERROR_CONDITION = static_cast(G_IO_ERR | G_ GIOCondition maskToGIOCondition(int mask) { - int ret = (mask & FdMask::READ ? G_IO_IN : 0) | - (mask & FdMask::WRITE ? G_IO_OUT : 0); + int ret = ((mask & FdMask::READ) ? G_IO_IN : 0) | + ((mask & FdMask::WRITE) ? G_IO_OUT : 0); return static_cast(ret); } @@ -97,7 +98,7 @@ bool isErrorCondition(GIOCondition condition) return !!(GIO_ERROR_CONDITION & condition); } -void print_prompt(Mode mode) +void printPrompt(Mode mode) { switch (mode) { case Mode::CLIENT: @@ -115,25 +116,118 @@ void print_prompt(Mode mode) fflush(stdout); } +const char *popupResultToString(ppm_popup_result_e result) +{ + switch (result) { + case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_ALLOW_FOREVER: + return "ALLOW_FOREVER"; + case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER: + return "DENY_FOREVER"; + case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE: + return "DENY_ONCE"; + } + + return "UNKNOWN"; +} + +void printClientHelp() +{ + printf("c check privilege status\n"); + printf("r send popup request\n"); + printf("s send popup request, additionally after receiving DENY it finishes this app\n"); + printf("h print help\n"); + printf("q quit\n"); + printPrompt(Mode::CLIENT); +} + +void printClientError(ppm_error_e error) +{ + switch (error) { + case PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE: + break; + case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR: + printf("I/O error\n"); + break; + case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER: + printf("Invalid parameters\n"); + break; + case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY: + printf("Out of memory\n"); + break; + case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN: + printf("Unknown error\n"); + break; + } +} + +void printClientCheckResult(ppm_check_result_e result) +{ + printf("res: "); + + switch (result) { + case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW: + printf("ALLOW\n"); + break; + case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY: + printf("DENY\n"); + break; + case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK: + printf("ASK\n"); + break; + } + + printPrompt(Mode::CLIENT); +} + +void printAppHelp(const char *programName) +{ + printf("Usage: %s [OPTIONS]\n", programName); + printf("Allows to test CAPI for Privacy Privilege Manager.\n"); + printf("This program can run in two modes: as a client and as a server.\n"); + printf("You can use it in two scenarios:\n"); + printf("1. Run as a client (%s -c) to trigger popups in the askuser-notification daemon.\n", programName); + printf("2. Run one part as a client (%s -c) and other one as a server (%s -s).\n", + programName, programName); + printf("If you want to run this program as a root you need to create /var/run/user_ext/0 folder.\n"); + printf("To run this program in context of some Tizen's application, type in the console:\n"); + printf("#echo > /proc/self/attr/current\n"); + printf("#su - \n\n"); + printf("Options:\n"); + printf("-s run as a server\n"); + printf("-c run as a client (uses CAPI)\n"); + printf("-h display this help end exit\n"); +} + +void printServerHelp() +{ + printf("l list all connections\n"); + printf("s list all requests\n"); + printf("ra send ALLOW FOREVER response\n"); + printf("rd send DENY FOREVER response\n"); + printf("ro send DENY ONCE response\n"); + printf("c close connection\n"); + printf("h print help\n"); + printf("q quit\n"); + printPrompt(Mode::SERVER); +} + struct ServerSimulator : public IServerCallbacks { ServerSimulator() : m_channel(nullptr) - { - } + {} virtual void newConnection(ConnectionFd fd, const Credentials &creds) { printf("\nnew connection fd: %d credentials = { label: \"%s\" uid: %s }", fd, creds.label.c_str(), creds.uid.c_str()); } - static gboolean server_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data) - { + static gboolean serverGIOCallback(GIOChannel *src, GIOCondition cond, gpointer data) { ServerSimulator *handle = static_cast(data); int fd = g_io_channel_unix_get_fd(src); - int events = (cond & G_IO_IN ? FdMask::READ : 0) | - (cond & G_IO_OUT ? FdMask::WRITE : 0); + int events = ((cond & G_IO_IN) ? FdMask::READ : 0) | + ((cond & G_IO_OUT) ? FdMask::WRITE : 0); handle->m_channel->process(fd, isErrorCondition(cond) ? 0 : events); @@ -163,7 +257,7 @@ struct ServerSimulator : public IServerCallbacks { m_requests.erase(fd); printf("Connection for fd: %d has been closed\n", fd); - print_prompt(Mode::SERVER); + printPrompt(Mode::SERVER); return; } @@ -175,7 +269,7 @@ struct ServerSimulator : public IServerCallbacks { guint watch_id = g_io_add_watch(gio_channel, makeCondition(gio_condition), - server_gio_cb, + serverGIOCallback, this); m_connections.insert({ fd, Connection{gio_channel, gio_condition, watch_id }}); @@ -190,7 +284,7 @@ struct ServerSimulator : public IServerCallbacks { g_source_remove(connection.watch_id); connection.watch_id = g_io_add_watch(connection.gio_channel, makeCondition(connection.condition), - server_gio_cb, + serverGIOCallback, this); } } @@ -198,15 +292,10 @@ struct ServerSimulator : public IServerCallbacks { virtual void popup(ConnectionFd fd, RequestId id, Privilege &&privilege) { printf("\npopup request fd: %d requestId: %d privilege: \"%s\"\n", fd, id, privilege.c_str()); addRequest(fd, id, privilege); - print_prompt(Mode::SERVER); + printPrompt(Mode::SERVER); } void addRequest(ConnectionFd fd, RequestId id, const Privilege &privilege) { - auto fdIt = m_requests.find(fd); - if (fdIt == m_requests.end()) { - m_requests.insert({ fd, PrivilegeRequestSet() }); - } - auto &s = m_requests[fd]; auto reqIt = s.find(id); @@ -257,7 +346,7 @@ struct ServerSimulator : public IServerCallbacks { auto it = m_connections.find(fd); if (it == m_connections.end()) { printf("ERROR: Connection fd: %d not found\n", fd); - print_prompt(Mode::SERVER); + printPrompt(Mode::SERVER); return; } @@ -282,307 +371,247 @@ private: std::map m_requests; }; -struct AppContext { +class AppContext { +public: AppContext() - : m_serverSimulator(nullptr) + : m_mainloop(g_main_loop_new(nullptr, FALSE)) + , m_serverSimulator(nullptr) , m_channel(nullptr) , m_mode(Mode::UNKNOWN) {} ~AppContext() { + g_main_loop_unref(m_mainloop); + if (m_channel != nullptr) { delete m_channel; } } - void initialize() { - if (m_mode == Mode::SERVER) { - m_serverSimulator = new ServerSimulator(); - m_channel = new ServerChannel(ServerCallbacksPtr(m_serverSimulator)); - m_serverSimulator->setServerChannel(m_channel); + void initialize(int argc, char **argv) { + if (argc < 1) { + throw std::logic_error("AppContext::initialize called with argc < 1"); } - } - - ServerSimulator *m_serverSimulator; - ServerChannel *m_channel; - Mode m_mode; -}; - -const char *popup_result_to_str(ppm_popup_result_e result) -{ - switch (result) { - case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_ALLOW_FOREVER: - return "ALLOW_FOREVER"; - case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER: - return "DENY_FOREVER"; - case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE: - return "DENY_ONCE"; - } - return "UNKNOWN"; -} - -void popup_response_cb(ppm_call_cause_e cause, ppm_popup_result_e result, void *user_data) -{ - ClientRequest *request = static_cast(user_data); - if (request == nullptr) { - printf("ERROR: User data is nullptr\n"); - return; - } + int c; + opterr = 0; + while ((c = getopt (argc, argv, "sch")) != -1) { + switch (c) { + case 's': + m_mode = Mode::SERVER; + break; + case 'c': + m_mode = Mode::CLIENT; + break; + case 'h': + default: + break; + } + } - printf("localId: %d privilege: \"%s\" ", request->m_id, request->m_privilege.c_str()); + switch (m_mode) { + case Mode::SERVER: + m_serverSimulator = new ServerSimulator(); + m_channel = new ServerChannel(ServerCallbacksPtr(m_serverSimulator)); + m_serverSimulator->setServerChannel(m_channel); + printServerHelp(); + break; + case Mode::CLIENT: + printClientHelp(); + break; + case Mode::UNKNOWN: + default: + printAppHelp(argv[0]); + exit(EXIT_SUCCESS); + } - switch (cause) { - case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER: - printf("popup response ANSWER: %s\n", popup_result_to_str(result)); - break; - case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR: - printf("popup response ERROR cause: PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR\n"); - break; + GIOChannel *gio_channel = g_io_channel_unix_new(0); + g_io_add_watch(gio_channel, static_cast(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), + &AppContext::mainLoopCallback, this); } - delete request; - - print_prompt(Mode::CLIENT); -} - -void print_client_help() -{ - printf("c check privilege status\n"); - printf("r send popup request\n"); - printf("h print help\n"); - printf("q quit\n"); - print_prompt(Mode::CLIENT); -} + void run() { + if (m_mode == Mode::UNKNOWN) { + throw std::logic_error("AppContext is not initialized"); + } -void print_client_error(ppm_error_e error) -{ - switch (error) { - case PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE: - break; - case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR: - printf("I/O error\n"); - break; - case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER: - printf("Invalid parameters\n"); - break; - case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY: - printf("Out of memory\n"); - break; - case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN: - printf("Unknown error\n"); - break; + g_main_loop_run(m_mainloop); } -} -static void print_client_check_result(ppm_check_result_e result) -{ - printf("res: "); +private: - switch (result) { - case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW: - printf("ALLOW\n"); - break; - case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY: - printf("DENY\n"); - break; - case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK: - printf("ASK\n"); - break; - } + static void popupResponseCallback(ppm_call_cause_e cause, ppm_popup_result_e result, void *user_data) { + ClientRequest *request = static_cast(user_data); + if (request == nullptr) { + printf("ERROR: User data is nullptr\n"); + return; + } - print_prompt(Mode::CLIENT); -} + printf("localId: %d privilege: \"%s\" ", request->m_id, request->m_privilege.c_str()); -void handle_client(char *buffer) -{ - ppm_check_result_e result; - ppm_error_e err = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE; - ClientRequest *request = nullptr; - char *privilege = nullptr; - static RequestId clientRequestId; - - switch (buffer[0]) { - case 'c': - if (strlen(buffer) < 3) { - print_client_help(); + switch (cause) { + case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER: + printf("popup response ANSWER: %s\n", popupResultToString(result)); break; - } - err = static_cast(ppm_check_privilege(&buffer[2], &result)); - if (err == PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) { - print_client_check_result(result); - } - break; - case 'r': - if (strlen(buffer) < 3) { - print_client_help(); + case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR: + printf("popup response ERROR cause: PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR\n"); break; - } - - buffer[strlen(buffer)] = '\0'; // erase new line - privilege = &buffer[2]; + } - printf("sending localId: %d privilege: \"%s\"\n", clientRequestId, privilege); + if (result == PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER && request->m_stopAppAfterDeny) { + g_main_loop_quit(request->m_mainLoop); + } - request = new ClientRequest{ clientRequestId++, privilege }; - err = static_cast(ppm_popup_request(privilege, popup_response_cb, request)); - if (err != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) { - delete request; - } + delete request; - break; - case 'q': - exit(EXIT_SUCCESS); - case 'h': - default: - print_client_help(); - return; + printPrompt(Mode::CLIENT); } - print_client_error(err); - print_prompt(Mode::CLIENT); -} + void handleClient(char *buffer) { + ppm_check_result_e result; + ppm_error_e err = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE; + ClientRequest *request = nullptr; + char *privilege = nullptr; + static RequestId clientRequestId; + bool stopAppAfterDeny = false; -void print_server_help() -{ - printf("l list all connections\n"); - printf("s list all requests\n"); - printf("ra send ALLOW FOREVER response\n"); - printf("rd send DENY FOREVER response\n"); - printf("ro send DENY ONCE response\n"); - printf("c close connection\n"); - printf("h print help\n"); - printf("q quit\n"); - print_prompt(Mode::SERVER); -} + switch (buffer[0]) { + case 'c': + if (strlen(buffer) < 3) { + printClientHelp(); + break; + } + err = static_cast(ppm_check_privilege(&buffer[2], &result)); + if (err == PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) { + printClientCheckResult(result); + } + break; + case 's': + stopAppAfterDeny = true; + case 'r': + if (strlen(buffer) < 3) { + printClientHelp(); + break; + } -void handle_server(const char *buffer, ServerSimulator *serverSimulator) -{ - int res; - ConnectionFd fd; - RequestId requestId; + buffer[strlen(buffer)] = '\0'; // erase new line + privilege = &buffer[2]; - switch (buffer[0]) { - case 'l': - serverSimulator->showConnections(); - break; - case 's': - serverSimulator->showPrivilegeRequests(); - break; - case 'r': - res = sscanf(&buffer[2], "%d %d", &fd, &requestId); - if (res != 2) { - print_server_help(); + printf("sending localId: %d privilege: \"%s\"\n", clientRequestId, privilege); + + request = new ClientRequest{ clientRequestId++, privilege, m_mainloop, stopAppAfterDeny }; + err = static_cast(ppm_popup_request(privilege, &AppContext::popupResponseCallback, request)); + if (err != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) { + delete request; + } + + break; + case 'q': + g_main_loop_quit(m_mainloop); return; - } - switch (buffer[1]) { - case 'a': - serverSimulator->sendResponse(fd, requestId, ASKUSER_ALLOW_FOREVER); - break; - case 'd': - serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_FOREVER); - break; - case 'o': - serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_ONCE); - break; - default: - print_server_help(); - return; - } - break; - case 'c': - res = sscanf(&buffer[1], "%d", &fd); - if (res != 1) { - print_server_help(); + case 'h': + default: + printClientHelp(); return; - } - serverSimulator->closeConnection(fd); - return; - case 'h': - print_server_help(); - return; - case 'q': - exit(EXIT_SUCCESS); + } + + printClientError(err); + printPrompt(Mode::CLIENT); } - print_prompt(Mode::SERVER); -} + void handleServer(const char *buffer) { + int res; + ConnectionFd fd; + RequestId requestId; -gboolean main_loop_cb(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, gpointer user_data) -{ - char buffer[4096]; + switch (buffer[0]) { + case 'l': + m_serverSimulator->showConnections(); + break; + case 's': + m_serverSimulator->showPrivilegeRequests(); + break; + case 'r': + res = sscanf(&buffer[2], "%d %d", &fd, &requestId); + if (res != 2) { + printServerHelp(); + return; + } + switch (buffer[1]) { + case 'a': + m_serverSimulator->sendResponse(fd, requestId, ASKUSER_ALLOW_FOREVER); + break; + case 'd': + m_serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_FOREVER); + break; + case 'o': + m_serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_ONCE); + break; + default: + printServerHelp(); + return; + } + break; + case 'c': + res = sscanf(&buffer[1], "%d", &fd); + if (res != 1) { + printServerHelp(); + return; + } + m_serverSimulator->closeConnection(fd); + return; + case 'h': + printServerHelp(); + return; + case 'q': + g_main_loop_quit(m_mainloop); + return; + } - int ret = read(0, buffer, sizeof(buffer)); - if (ret <= 0) { - printf("read from stdin failed\n"); - exit(EXIT_FAILURE); + printPrompt(Mode::SERVER); } - buffer[ret - 1] = '\0'; + static gboolean mainLoopCallback(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, gpointer user_data) { + char buffer[4096]; - AppContext *ctx = static_cast(user_data); - switch (ctx->m_mode) { - case Mode::CLIENT: - handle_client(buffer); - break; - case Mode::SERVER: - handle_server(buffer, ctx->m_serverSimulator); - break; - case Mode::UNKNOWN: - default: - printf("Mode not set, exiting.\n"); + int ret = read(0, buffer, sizeof(buffer)); + if (ret <= 0) { + printf("read from stdin failed\n"); exit(EXIT_FAILURE); - } - - return TRUE; -} - -void print_help(const char *programName) -{ - printf("Usage: %s [OPTIONS]\n", programName); - printf("Allows to test CAPI for Privacy Privilege Manager.\n"); - printf("This program can run in two modes: as a client and as a server.\n"); - printf("You can use it in two scenarios:\n"); - printf("1. Run as a client (%s -c) to trigger popups in the askuser-notification daemon.\n", programName); - printf("2. Run one part as a client (%s -c) and other one as a server (%s -s).\n", - programName, programName); - printf("If you want to run this program as a root you need to create /var/run/user_ext/0 folder.\n"); - printf("To run this program in context of some Tizen's application, type in the console:\n"); - printf("#echo > /proc/self/attr/current\n"); - printf("#su - \n\n"); - printf("Options:\n"); - printf("-s run as a server\n"); - printf("-c run as a client (uses CAPI)\n"); - printf("-h display this help end exit\n"); -} + } -int main(int argc, char **argv) -{ - AppContext ctx; - int c; + buffer[ret - 1] = '\0'; - opterr = 0; - while ((c = getopt (argc, argv, "sch")) != -1) { - switch (c) { - case 's': - ctx.m_mode = Mode::SERVER; + AppContext *ctx = static_cast(user_data); + switch (ctx->m_mode) { + case Mode::CLIENT: + ctx->handleClient(buffer); break; - case 'c': - ctx.m_mode = Mode::CLIENT; + case Mode::SERVER: + ctx->handleServer(buffer); break; - case 'h': + case Mode::UNKNOWN: default: - break; + printf("Mode not set, exiting.\n"); + exit(EXIT_FAILURE); } - } - if (ctx.m_mode == Mode::UNKNOWN) { - print_help(argv[0]); - exit(EXIT_SUCCESS); + return TRUE; } + GMainLoop *m_mainloop; + ServerSimulator *m_serverSimulator; + ServerChannel *m_channel; + Mode m_mode; +}; + +int main(int argc, char **argv) +{ + AppContext appCtx; + try { - ctx.initialize(); + appCtx.initialize(argc, argv); + appCtx.run(); } catch (const ConnectionException &e) { printf("Connection exception occured during initialization: %s, exiting.\n", e.what()); @@ -598,26 +627,5 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - switch (ctx.m_mode) { - case Mode::SERVER: - print_server_help(); - break; - case Mode::CLIENT: - print_client_help(); - break; - case Mode::UNKNOWN: - default: - printf("Unknown mode\n"); - exit(EXIT_FAILURE); - } - - GMainLoop *mainloop = g_main_loop_new(nullptr, FALSE); - - GIOChannel *gio_channel = g_io_channel_unix_new(0); - g_io_add_watch(gio_channel, static_cast(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), - main_loop_cb, &ctx); - - g_main_loop_run(mainloop); - return 0; } -- 2.7.4