summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJanusz Kozerski <j.kozerski@samsung.com>2015-06-22 15:07:51 +0200
committerJanusz Kozerski <j.kozerski@samsung.com>2015-08-03 16:14:30 +0200
commita091055a43789a3fb3586dd364ba857765b685cc (patch)
tree639c9245f193556cd300529ef04eba1d484d0755 /src
parent6be76744f1e8a8291b410437867cd2c1ca9b576a (diff)
downloadcert-checker-a091055a43789a3fb3586dd364ba857765b685cc.tar.gz
cert-checker-a091055a43789a3fb3586dd364ba857765b685cc.tar.bz2
cert-checker-a091055a43789a3fb3586dd364ba857765b685cc.zip
Add popup UI (+tests)
Notification framework currently doesn't work properly on tizen.org/common. To test UI run: cert-checker-popup-test, and check if UI is displayed correctly. Change-Id: I0eb9b134c77c82eb77b4834b81a1cd1fa19dd620
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/cert-checker.cpp1
-rw-r--r--src/include/cchecker/UIBackend.h59
-rw-r--r--src/include/cchecker/logic.h4
-rw-r--r--src/logic.cpp47
-rw-r--r--src/po/CMakeLists.txt44
-rw-r--r--src/po/en.po14
-rw-r--r--src/po/pl.po14
-rw-r--r--src/ui/UIBackend.cpp218
9 files changed, 398 insertions, 7 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d5a56eb..e61cf4a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -36,6 +36,8 @@ SET(CERT_CHECKER_SOURCES
${CERT_CHECKER_SRC_PATH}/dpl/db/src/naive_synchronization_object.cpp
# DB
${CERT_CHECKER_SRC_PATH}/db/sql_query.cpp
+ # UI
+ ${CERT_CHECKER_SRC_PATH}/ui/UIBackend.cpp
)
INCLUDE_DIRECTORIES(SYSTEM
@@ -52,3 +54,5 @@ TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER}
)
INSTALL(TARGETS ${TARGET_CERT_CHECKER} DESTINATION ${BINDIR})
+
+ADD_SUBDIRECTORY(po)
diff --git a/src/cert-checker.cpp b/src/cert-checker.cpp
index e754d94..c6e7537 100644
--- a/src/cert-checker.cpp
+++ b/src/cert-checker.cpp
@@ -31,6 +31,7 @@ int main(void)
{
LogDebug("Cert-checker start!");
+ setlocale(LC_ALL, "");
GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
Logic logic;
diff --git a/src/include/cchecker/UIBackend.h b/src/include/cchecker/UIBackend.h
new file mode 100644
index 0000000..e59f0d7
--- /dev/null
+++ b/src/include/cchecker/UIBackend.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file UIBackend.h
+ * @author Janusz Kozerski <j.kozerski@samsung.com>
+ * @brief This file declares class for ask user window
+ */
+
+#pragma once
+
+#include <notification.h>
+
+#include <cchecker/app.h>
+
+namespace CCHECKER {
+namespace UI {
+
+enum response_e {
+ DONT_UNINSTALL,
+ UNINSTALL,
+ ERROR
+};
+
+// FIXME: notification framework is corrupted and it doesn't work as it should
+
+class UIBackend {
+public:
+ explicit UIBackend(int timeout = 60); //timeout in seconds
+ virtual ~UIBackend();
+
+ // Displays popup with question, and - if needed - app_control for removing application.
+ // Returns true if UI was displayed correctly and user's response was collected.
+ // If there was a problem with displaying UI or a timeout has been reached (no user's response)
+ // then returns false.
+ bool call_popup(const app_t &app);
+
+private:
+ response_e run();
+ bool create_ui(const std::string &app_id, const std::string &pkg_id);
+
+ notification_h m_notification;
+ const int m_responseTimeout; // seconds
+};
+
+} // UI
+} // CCHECKER
diff --git a/src/include/cchecker/logic.h b/src/include/cchecker/logic.h
index cf1c63d..aa50388 100644
--- a/src/include/cchecker/logic.h
+++ b/src/include/cchecker/logic.h
@@ -100,7 +100,7 @@ class Logic {
void process_all(void);
void process_queue(void);
void process_event(const event_t &event);
- error_t process_buffer(void);
+ void process_buffer(void);
bool get_online(void) const;
void set_online(bool online);
@@ -108,6 +108,8 @@ class Logic {
bool get_should_exit(void) const;
void set_should_exit(void);
+ void call_ui(const app_t &app);
+
Queue m_queue;
Certs m_certs;
std::list<app_t> m_buffer;
diff --git a/src/logic.cpp b/src/logic.cpp
index 63c2e15..aef6aec 100644
--- a/src/logic.cpp
+++ b/src/logic.cpp
@@ -21,13 +21,18 @@
*/
#include <stdexcept>
#include <tzplatform_config.h>
+#include <app_control_internal.h>
#include <cchecker/logic.h>
#include <cchecker/log.h>
#include <cchecker/sql_query.h>
+#include <cchecker/UIBackend.h>
using namespace std;
+// FIXME: Popup temporary disabled
+#define POPUP 0
+
namespace CCHECKER {
namespace {
@@ -376,12 +381,39 @@ void Logic::process_queue(void)
}
}
-error_t Logic::process_buffer(void)
+void Logic::call_ui(const app_t &app)
+{
+ UI::UIBackend ui;
+
+ if (ui.call_popup(app)) { // If calling popup or app_controll service will fail,
+ // do not remove application, and ask about it once again later
+ remove_app_from_buffer_and_database(app);
+ LogDebug("Popup shown correctly. Application will be removed from DB and buffer");
+ }
+ else
+ LogDebug("Popup error. Application will be marked to show popup later.");
+}
+
+void Logic::process_buffer(void)
{
for (auto iter = m_buffer.begin(); iter != m_buffer.end();) {
- // If OCSP checking fails we should remove application from buffer and database
+
+ // Check if app hasn't already been verified.
+ // If yes then just try to display popup once again, and go the next app.
+#if POPUP
+ if (iter->verified == app_t::verified_t::NO) {
+ app_t app_cpy = *iter;
+ LogDebug(app_cpy.str() << " has been verified before. Popup should be shown.");
+ call_ui(app_cpy);
+ iter++;
+ continue;
+ }
+#endif
+
Certs::ocsp_response_t ret;
ret = m_certs.check_ocsp(*iter);
+
+ // If OCSP returns success or OCSP checking fails we should remove application from buffer and database
if (ret == Certs::ocsp_response_t::OCSP_APP_OK ||
ret == Certs::ocsp_response_t::OCSP_CERT_ERROR) {
LogDebug(iter->str() << " OCSP verified (or not available for app's chains)");
@@ -391,12 +423,16 @@ error_t Logic::process_buffer(void)
}
else if (ret == Certs::ocsp_response_t::OCSP_APP_REVOKED) {
LogDebug(iter->str() << " certificate has been revoked. Popup should be shown");
+ iter->verified = app_t::verified_t::NO;
app_t app_cpy = *iter;
iter++;
- // TODO: Do not remove app here - just waits for user answer from popup
- // Temporary solution because popup doesn't work
+#if POPUP
+// Do not remove app here - just waits for user answer from popup
+// Temporary solution because notification framework doesn't work
+ call_ui(app_cpy);
+#else
remove_app_from_buffer_and_database(app_cpy);
-
+#endif
}
else {
LogDebug(iter->str() << " should be checked again later");
@@ -405,7 +441,6 @@ error_t Logic::process_buffer(void)
iter++;
}
}
- return NO_ERROR;
}
void Logic::process_all()
diff --git a/src/po/CMakeLists.txt b/src/po/CMakeLists.txt
new file mode 100644
index 0000000..3cb076f
--- /dev/null
+++ b/src/po/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright (c) 2015 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.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# @file CMakeLists.txt
+# @author Adam Malinowski <a.malinowsk2@partner.samsung.com>
+#
+
+SET(POFILES
+ en.po pl.po
+)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(SHAREDIR "${PREFIX}/share")
+SET(LOCALEDIR "${SHAREDIR}/locale")
+SET(MSGFMT "/usr/bin/msgfmt")
+
+FOREACH(pofile ${POFILES})
+ SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile})
+ MESSAGE("PO: ${pofile}")
+ GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE)
+ GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE)
+ SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo)
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${moFile}
+ COMMAND ${MSGFMT} -o ${moFile} ${absPofile}
+ DEPENDS ${absPofile}
+ )
+ INSTALL(FILES ${moFile}
+ DESTINATION ${LOCALEDIR}/${lang}/LC_MESSAGES RENAME ${PROJECT_NAME}.mo)
+ SET(moFiles ${moFiles} ${moFile})
+ENDFOREACH(pofile)
+
+ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles})
diff --git a/src/po/en.po b/src/po/en.po
new file mode 100644
index 0000000..764b151
--- /dev/null
+++ b/src/po/en.po
@@ -0,0 +1,14 @@
+msgid "SID_TITLE_OCSP_VERIFICATION_FAILED"
+msgstr "OCSP verification failed"
+
+msgid "SID_CONTENT_OCSP_VERIFICATION_FAILED"
+msgstr "A certificate of an application %s (%s) was revoked."
+
+msgid "SID_CONTENT_OCSP_PACKAGE VERIFICATION_FAILED"
+msgstr "A certificate of one of applications in package %s was revoked."
+
+msgid "SID_BTN_OCSP_KEEP_APP"
+msgstr "Keep"
+
+msgid "SID_BTN_OCSP_UNINSTALL_APP"
+msgstr "Uninstall"
diff --git a/src/po/pl.po b/src/po/pl.po
new file mode 100644
index 0000000..cff940e
--- /dev/null
+++ b/src/po/pl.po
@@ -0,0 +1,14 @@
+msgid "SID_TITLE_OCSP_VERIFICATION_FAILED"
+msgstr "Veryfikacja OCSP nie powiodła się"
+
+msgid "SID_CONTENT_OCSP_VERIFICATION_FAILED"
+msgstr "Certifikat aplikacji %s (%s) został odwołany."
+
+msgid "SID_CONTENT_OCSP_PACKAGE VERIFICATION_FAILED"
+msgstr "Certyfikat jednej z aplikacji w pakiecie %s został odwołany."
+
+msgid "SID_BTN_OCSP_KEEP_APP"
+msgstr "Zachowaj"
+
+msgid "SID_BTN_OCSP_UNINSTALL_APP"
+msgstr "Usuń"
diff --git a/src/ui/UIBackend.cpp b/src/ui/UIBackend.cpp
new file mode 100644
index 0000000..5fd33a4
--- /dev/null
+++ b/src/ui/UIBackend.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file UIBackend.cpp
+ * @author Janusz Kozerski <j.kozerski@samsung.com>
+ * @brief This file implements class for ask user window
+ */
+
+#include <bundle.h>
+#include <cerrno>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <libintl.h>
+#include <notification_internal.h>
+#include <notification_error.h>
+#include <app_control_internal.h>
+
+#include <cchecker/log.h>
+#include <cchecker/UIBackend.h>
+
+namespace CCHECKER {
+namespace UI {
+
+namespace { // anonymus
+const char *errorToString(int error) {
+ if (error == NOTIFICATION_ERROR_INVALID_PARAMETER)
+ return "NOTIFICATION_ERROR_INVALID_PARAMETER";
+ if (error == NOTIFICATION_ERROR_OUT_OF_MEMORY)
+ return "NOTIFICATION_ERROR_OUT_OF_MEMORY";
+ if (error == NOTIFICATION_ERROR_FROM_DB)
+ return "NOTIFICATION_ERROR_FROM_DB";
+ if (error == NOTIFICATION_ERROR_ALREADY_EXIST_ID)
+ return "NOTIFICATION_ERROR_ALREADY_EXIST_ID";
+ if (error == NOTIFICATION_ERROR_FROM_DBUS)
+ return "NOTIFICATION_ERROR_FROM_DBUS";
+ if (error == NOTIFICATION_ERROR_NOT_EXIST_ID)
+ return "NOTIFICATION_ERROR_NOT_EXIST_ID";
+ if (error == NOTIFICATION_ERROR_IO_ERROR)
+ return "NOTIFICATION_ERROR_IO_ERROR";
+ if (error == NOTIFICATION_ERROR_SERVICE_NOT_READY)
+ return "NOTIFICATION_ERROR_SERVICE_NOT_READY";
+ if (error == NOTIFICATION_ERROR_NONE)
+ return "NOTIFICATION_ERROR_NONE";
+
+ return "UNHANDLED ERROR";
+}
+} // anonymus
+
+UIBackend::UIBackend(int timeout) :
+ m_notification(nullptr),
+ m_responseTimeout(timeout)
+{}
+
+UIBackend::~UIBackend() {
+ notification_free(m_notification);
+}
+
+bool UIBackend::create_ui(const std::string &app_id, const std::string &pkg_id)
+{
+ if(m_notification) {
+ notification_free(m_notification);
+ m_notification = nullptr;
+ }
+
+ m_notification = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (m_notification == nullptr) {
+ LogError("Failed to create notification.");
+ return false;
+ }
+
+ int err = notification_set_pkgname(m_notification, "cert-checker");
+ if (err != NOTIFICATION_ERROR_NONE) {
+ LogError("Unable to set notification pkgname: <" << errorToString(err) << ">");
+ return false;
+ }
+
+ // Set title
+ char *dialogTitle = dgettext(PROJECT_NAME, "SID_TITLE_OCSP_VERIFICATION_FAILED");
+ err = notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_TITLE, dialogTitle, nullptr,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ LogError("Unable to set notification title: <" << errorToString(err) << ">");
+ return false;
+ }
+
+ // Set message
+ // App ID may be absent, so in that case we need to use only package ID
+ if (app_id == std::string(TEMP_APP_ID)) {
+ char *content = dgettext(PROJECT_NAME, "SID_CONTENT_OCSP_PACKAGE VERIFICATION_FAILED");
+ err = notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_CONTENT, content, nullptr,
+ NOTIFICATION_VARIABLE_TYPE_STRING, pkg_id.c_str(),
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ }
+ else {
+ char *content = dgettext(PROJECT_NAME, "SID_CONTENT_OCSP_VERIFICATION_FAILED");
+ err = notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_CONTENT, content, nullptr,
+ NOTIFICATION_VARIABLE_TYPE_STRING, app_id.c_str(),
+ NOTIFICATION_VARIABLE_TYPE_STRING, pkg_id.c_str(),
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ }
+ if (err != NOTIFICATION_ERROR_NONE) {
+ LogError("Unable to set notification content: <" << errorToString(err) << ">");
+ return false;
+ }
+
+ char *btn_keep = dgettext(PROJECT_NAME, "SID_BTN_OCSP_KEEP_APP");
+ char *btn_uninstall = dgettext(PROJECT_NAME, "SID_BTN_OCSP_UNINSTALL_APP");
+
+ std::string buttons = std::string(btn_keep) + std::string(",") + std::string(btn_uninstall);
+
+ bundle *b = bundle_create();
+ if (!b) {
+ int erryes = errno;
+ LogError("Unable to create bundle: <" << strerror(erryes) << ">");
+ return false;
+ }
+
+ if (bundle_add(b, "buttons", buttons.c_str())) {
+ int erryes = errno;
+ LogError("Unable to add button to bundle: <" << strerror(erryes) << ">");
+ bundle_free(b);
+ return false;
+ }
+
+ err = notification_set_execute_option(m_notification, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
+ nullptr, nullptr, b);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ LogError("Unable to set execute option: <" << errorToString(err) << ">");
+ bundle_free(b);
+ return false;
+ }
+ bundle_free(b);
+
+ err = notification_insert(m_notification, nullptr);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ LogError("Unable to insert notification: <" << errorToString(err) << ">");
+ return false;
+ }
+
+ return true;
+}
+
+response_e UIBackend::run()
+{
+ response_e response = response_e(ERROR);
+ try {
+ int buttonClicked = 0;
+ int ret = notification_wait_response(m_notification, m_responseTimeout,
+ &buttonClicked, nullptr);
+ LogDebug("notification_wait_response finished with ret code: [" << ret << "]");
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ // FIXME: magic numbers
+ if (buttonClicked == 1) {
+ response = response_e(DONT_UNINSTALL);
+ LogDebug("notification_wait_response, button clicked: DON'T UNINSTALL");
+ } else if (buttonClicked == 2) {
+ response = response_e(UNINSTALL);
+ LogDebug("notification_wait_response, Button clicked: UNINSTALL");
+ } else {
+ response = response_e(ERROR);
+ LogError("notification_wait_response, timeouted");
+ }
+ }
+ } catch (const std::exception &e) {
+ LogError("Unexpected exception: <" << e.what() << ">");
+ } catch (...) {
+ LogError("Unexpected unknown exception caught!");
+ }
+ return response;
+}
+
+bool UIBackend::call_popup(const app_t &app)
+{
+ response_e resp;
+
+ create_ui(app.app_id, app.pkg_id);
+ resp = run();
+ LogDebug(app.str() << " response: " << resp);
+ if (resp == ERROR) {
+ return false;
+ }
+
+ else if (resp == UNINSTALL) {
+ app_control_h service = NULL;
+ int result = 0;
+ result = app_control_create(&service);
+ if (!service || result != APP_CONTROL_ERROR_NONE) {
+ return false;
+ }
+ app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+ app_control_set_app_id(service, "setting-manage-applications-efl");
+ app_control_add_extra_data(service, "viewtype", "application-info");
+ app_control_add_extra_data(service, "pkgname", app.pkg_id.c_str());
+ app_control_send_launch_request(service, NULL, NULL);
+ app_control_destroy(service);
+ }
+ return true;
+}
+
+} // UI
+} // CCHECKER