#define __UI_PRIVACY_SETTING_COMMON_CTXPOPUP_H_
#include "common_utils.h"
-#include <Elementary.h>
+#include <efl_extension.h>
/**
* @brief create a ctxpopup object
* @param[in] button1_cb The callback function for when button1 is clicked
* @param[in] button2_label The button text for button2
* @param[in] button2_cb The callback function for when button2 is clicked
- * @param[in] dismiss_popup_cb The callback function for when the popup is dismissed
+ * @param[in] back_btn_cb The callback function for when the hardware back button is pressed
* @param[in] data User data to be passed to the callback funtions
*
* @return the ctxpopup object
Evas_Smart_Cb button1_cb,
const char *button2_label,
Evas_Smart_Cb button2_cb,
- Evas_Smart_Cb dismiss_popup_cb,
+ Evas_Smart_Cb back_btn_cb,
void* data);
#endif
*/
bool get_pattern_ids_in_use_list(GList **patterns_not_in_use_list);
+/**
+ * @brief check if parameters form a valid rule
+ * @param[in] name the rule name
+ * @param[in] description the rule description
+ * @param[in] pattern the rule pattern
+ *
+ * @return true if the rule is valid, false if otherwise
+*/
+bool is_valid_rule(const char *name, const char *description, const get_pattern_s *pattern);
+
+/**
+ * @brief check if parameters form a valid pattern
+ * @param[in] name the pattern name
+ * @param[in] description the pattern description
+ * @param[in] type the pattern type
+ * @param[in] search_term the pattern search term
+ *
+ * @return true if the pattern is valid, false if otherwise
+*/
+bool is_valid_pattern(const char *name, const char *description, PgDlpPatternType type, const char *search_term);
+
+/**
+ * @brief remove leading spaces from a string. Note: string will be changed in-place
+ * @param[in,out] text the string to be left trimmed
+ * @param[in] len_text the lenght of the string to be left trimmed
+ */
+void left_trim(char *text, const size_t len_text);
+
#ifdef _cplusplus
}
#endif
*/
#include "common_ctxpopup.h"
-#include <efl_extension.h>
-static void _dismiss_menu_cb(void *data, Evas_Object *obj, void *event_info)
+static void _back_cb(void *data, Evas_Object *obj, void *event_info)
{
- delete_ctxpopup(obj);
+ elm_ctxpopup_dismiss(obj);
}
-void move_menu_popup(Evas_Object *app_win, Evas_Object *ctxpopup)
+static void move_menu_popup(Evas_Object *app_win, Evas_Object *ctxpopup)
{
Evas_Coord w, h;
int pos = -1;
Evas_Object *ctxpopup = elm_ctxpopup_add(ad->nf);
elm_object_style_set(ctxpopup, "more/default");
elm_ctxpopup_auto_hide_disabled_set(ctxpopup, EINA_TRUE);
- eext_object_event_callback_add(ctxpopup, EEXT_CALLBACK_BACK, _dismiss_menu_cb, NULL);
- evas_object_smart_callback_add(ctxpopup, "dismissed", _dismiss_menu_cb, NULL);
+ eext_object_event_callback_add(ctxpopup, EEXT_CALLBACK_BACK, _back_cb, NULL);
move_menu_popup(ad->win, ctxpopup);
evas_object_show(ctxpopup);
return ctxpopup;
evas_object_smart_callback_add(data->entry, "focused", _edit_field_focused_cb, data->edit_field);
evas_object_smart_callback_add(data->entry, "unfocused", _edit_field_unfocused_cb, data->edit_field);
evas_object_smart_callback_add(data->entry, "changed", _edit_field_changed_cb, data);
- evas_object_smart_callback_add(data->entry, "preedit,changed", _edit_field_changed_cb, data->edit_field);
Evas_Object *clear_button = elm_button_add(data->edit_field);
elm_object_style_set(clear_button, "editfield_clear");
evas_object_smart_callback_add(button, "clicked", button_callback, data);
}
-Evas_Object* create_two_buttons_popup(Evas_Object *parent, const char *popup_title, const char *popup_text,
- const char *button1_label, Evas_Smart_Cb button1_cb, const char *button2_label,
- Evas_Smart_Cb button2_cb, Evas_Smart_Cb dismiss_popup_cb, void* data)
+Evas_Object* create_two_buttons_popup(
+ Evas_Object *parent,
+ const char *popup_title,
+ const char *popup_text,
+ const char *button1_label,
+ Evas_Smart_Cb button1_cb,
+ const char *button2_label,
+ Evas_Smart_Cb button2_cb,
+ Evas_Smart_Cb back_btn_cb,
+ void* data)
{
/* Create the popup */
Evas_Object *popup = elm_popup_add(parent);
add_button_to_popup(popup, data, button1_label, "button1", button1_cb);
add_button_to_popup(popup, data, button2_label, "button2", button2_cb);
- /* Add callback to popup dismiss popup when user press the hardware back key */
- eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, dismiss_popup_cb, data);
+ /* Add callback to be called when user press the hardware back key */
+ eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, back_btn_cb, data);
/* Display popup */
evas_object_show(popup);
return true;
}
+
+// Gets position of first non-space character in a string
+static size_t get_first_non_space_pos(const char *text, const size_t len_text)
+{
+ if (NULL == text || 0 == len_text) {
+ LOGE("Invalid parameter");
+ return false;
+ }
+
+ size_t pos = 0;
+ for (; pos < len_text && '\0' != text[pos] && ' ' == text[pos]; ++pos);
+ return pos;
+}
+
+// check if a text field (ususally rule or pattern name and description) is valid.
+// text is considered valid if it is not empty and contains a non-space character.
+static bool is_valid_text_field(const char *text, const size_t len_text)
+{
+ if (NULL == text || 0 == len_text) {
+ LOGE("Invalid parameter");
+ return false;
+ }
+
+ const size_t pos = get_first_non_space_pos(text, len_text);
+ return '\0' != text[pos];
+}
+
+bool is_valid_rule(const char *name, const char *description, const get_pattern_s *pattern)
+{
+ return is_valid_text_field(name, LEN_NAME)
+ && is_valid_text_field(description, LEN_DESCRIPTION)
+ && NULL != pattern;
+}
+
+bool is_valid_pattern(const char *name, const char *description, PgDlpPatternType type, const char *search_term)
+{
+ if (!is_valid_text_field(name, LEN_NAME)
+ || !is_valid_text_field(description, LEN_DESCRIPTION))
+ return false;
+
+ if (PRIV_GUARD_DLP_PATTERN_STRING == type)
+ return is_valid_text_field(search_term, LEN_PATTERN);
+ else
+ return PRIV_GUARD_ERROR_SUCCESS == privacy_guard_client_validate_pattern(type, search_term);
+}
+
+void left_trim(char *text, const size_t len_text)
+{
+ if (NULL == text || 0 == len_text) {
+ LOGE("Invalid parameter");
+ return;
+ }
+
+ const size_t pos = get_first_non_space_pos(text, len_text);
+ if (pos > 0)
+ for (size_t i = pos; i < len_text; ++i)
+ text[i - pos] = text[i];
+}
#include "privacy_view.h"
#include <privacy_guard_client.h>
#include <app_manager.h>
+#include <string.h>
+
+#define DEFAULT_ICON_PATH _TZ_SYS_RO_APP"/org.tizen.privacy-setting/res/icon/default.png"
typedef struct {
struct app_data_s *ad;
return strcmp((const char *)lhs, (const char *)rhs);
}
+static char *make_default_app_name(const char *app_id)
+{
+ // uses the last field of the app_id as default app name
+ const char* def_app_name = strrchr(app_id, '.');
+ if (NULL == def_app_name)
+ def_app_name = app_id; // if a dot is not found then use the app_id as default app name
+ else
+ ++def_app_name; // skip the dot
+
+ return strdup(def_app_name); // this must be freed by the caller
+}
+
/**
* @brief Internal callback function used to retrieve application information
* @param[in] app_info appliation handle
res = app_info_get_label(app_info, &label);
if (res < 0) {
LOGE("%s: app_info_get_label() failed. Error=%d", app->id, res);
- app->name = strdup("");
+ app->name = make_default_app_name(app->id);
} else {
+ if ('\0' == label[0]) {
+ free(label);
+ label = make_default_app_name(app->id);
+ }
app->name = label;
}
res = app_info_get_icon(app_info, &(app->icon_path));
if (res < 0) {
LOGE("app_info_get_icon() failed. Error=%d", res);
- app->icon_path = strdup("");
+ app->icon_path = strdup(DEFAULT_ICON_PATH);
}
choose_app_data_s *choose_app_data = user_data;
if (strcmp(part, "elm.swallow.icon") == 0) {
if (SELECT_ALL_APPS_ITEM_ID != app_item->id) {
Evas_Object *icon = elm_icon_add(obj);
- elm_image_file_set(icon, app_item->icon_path, NULL);
+ if (!elm_image_file_set(icon, app_item->icon_path, NULL))
+ // Sometimes an app has a non-empty icon path, but still fails to set the icon image.
+ // In these cases, we set the default icon to app
+ elm_image_file_set(icon, DEFAULT_ICON_PATH, NULL);
evas_object_size_hint_min_set(icon, ELM_SCALE_SIZE(50), ELM_SCALE_SIZE(50));
return icon;
}
}
}
+static void add_select_all_item_to_genlist(choose_app_data_s *data)
+{
+ Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
+ itc->item_style = "singleline";
+ itc->func.text_get = _gl_choose_app_text_get_cb;
+ itc->func.content_get = _gl_choose_app_content_get_cb;
+ itc->func.del = NULL;
+
+ Elm_Object_Item *it = elm_genlist_item_append(data->genlist, itc, data->app_list->data, NULL, ELM_GENLIST_ITEM_NONE, _choose_app_menu_item_selected_cb, data);
+ log_if(it == NULL, 1, "Error in elm_genlist_item_append");
+
+ elm_genlist_item_class_free(itc);
+}
+
+
/**
* @brief Displays the Choose Applications view
* @param[in] ad the appliation data
evas_object_size_hint_weight_set(data.genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(data.genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ add_select_all_item_to_genlist(&data);
Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
itc->item_style = "multiline";
itc->func.text_get = _gl_choose_app_text_get_cb;
itc->func.del = NULL;
Elm_Object_Item *it = NULL;
GList* l;
- for (l = data.app_list; l != NULL; l = l->next) {
+ for (l = g_list_nth(data.app_list, 1); l != NULL; l = l->next) {
// append item to the genlist
it = elm_genlist_item_append(data.genlist, itc, l->data, NULL, ELM_GENLIST_ITEM_NONE, _choose_app_menu_item_selected_cb, &data);
log_if(it == NULL, 1, "Error in elm_genlist_item_append");
}
/**
+ * @brief Internal callback function called when DLP on/off item is selected
+ * @param[in] data The user data passed to the elm_genlist_item_append() function
+ * @param[in] obj The object invoking this callback function
+ * @param[in] event_info The structure containing the information on this event
+ */
+static void _gl_enabled_item_select_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ /* Unhighlight selected item */
+ elm_genlist_item_selected_set(event_info, EINA_FALSE);
+
+ /* get check object */
+ Evas_Object *check = elm_object_item_part_content_get(event_info, "elm.swallow.end");
+
+ /* flip dlp enabled state */
+ config.enabled = elm_check_state_get(check) ? 0 : 1;
+
+ const int res = privacy_guard_client_set_dlp_profile(getuid(), &config);
+ if (PRIV_GUARD_ERROR_SUCCESS == res) {
+ elm_check_state_set(check, config.enabled ? EINA_TRUE : EINA_FALSE);
+ } else {
+ LOGE("privacy_guard_client_set_dlp_profile() is failed. [%d]", res);
+ }
+}
+
+/**
* @brief Internal callback function when default profile is selected.
* @param[in] data The user data passed to the evas_object_smart_callback_add() function
* @param[in] obj The object invoking this callback function
itc_enabled->func.content_get = _gl_enabled_content_get_cb;
itc_enabled->func.del = _gl_del_config_cb;
- elm_genlist_item_append(genlist, itc_enabled, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ elm_genlist_item_append(genlist, itc_enabled, NULL, NULL, ELM_GENLIST_ITEM_NONE, _gl_enabled_item_select_cb, NULL);
elm_genlist_item_class_free(itc_enabled);
// Option to Select Protection Mode
static void _pattern_create_field_changed_cb(void *data, Evas_Object *obj, void* event_info)
{
pattern_create_view_data_s *pcvd = data;
- if (!is_edit_field_empty(pcvd->name_edit_field)
- && !is_edit_field_empty(pcvd->description_edit_field)
- && PRIV_GUARD_ERROR_SUCCESS == privacy_guard_client_validate_pattern(pcvd->current_type, get_text_from_edit_field(pcvd->search_string_edit_field)))
+ if (is_valid_pattern(
+ get_text_from_edit_field(pcvd->name_edit_field),
+ get_text_from_edit_field(pcvd->description_edit_field),
+ pcvd->current_type,
+ get_text_from_edit_field(pcvd->search_string_edit_field)))
elm_object_disabled_set(pcvd->done_button, EINA_FALSE);
else
elm_object_disabled_set(pcvd->done_button, EINA_TRUE);
{
pattern_create_view_data_s *pcvd = data;
+ char name[LEN_NAME];
+ strncpy(name, get_text_from_edit_field(pcvd->name_edit_field), LEN_NAME);
+ left_trim(name, LEN_NAME);
+ name[LEN_NAME - 1] = '\0';
+
+ char description[LEN_DESCRIPTION];
+ strncpy(description, get_text_from_edit_field(pcvd->description_edit_field), LEN_DESCRIPTION);
+ left_trim(description, LEN_DESCRIPTION);
+ description[LEN_DESCRIPTION - 1] = '\0';
+
const int res = privacy_guard_client_add_dlp_pattern(
- get_text_from_edit_field(pcvd->name_edit_field),
- get_text_from_edit_field(pcvd->description_edit_field),
+ name,
+ description,
elm_object_text_get(pcvd->category_hoversel),
get_text_from_edit_field(pcvd->search_string_edit_field),
pcvd->current_type);
int size = snprintf(string_buf, REPORT_TOTAL_LEAKS_LEN, "%s: %d<br>From: ",
dgettext("privacy-setting", PRIVACY_MENU_DLP_REPORTS_TOTAL_LEAKS), item->leak_count);
- struct tm *timestamp = gmtime(&item->first_time_stamp);
- size += strftime(string_buf + size, 100 - size, "%b %d, %Y - To: ", timestamp);
+ struct tm timestamp;
+ gmtime_r(&item->first_time_stamp, ×tamp);
+ size += strftime(string_buf + size, 100 - size, "%b %d, %Y - To: ", ×tamp);
- timestamp = gmtime(&item->last_time_stamp);
- size += strftime(string_buf + size, 100 - size, "%b %d, %Y", timestamp);
+ gmtime_r(&item->last_time_stamp, ×tamp);
+ size += strftime(string_buf + size, 100 - size, "%b %d, %Y", ×tamp);
char *multiline = strdup(string_buf);
int size = snprintf(string_buf, 100, "%s: %d<br>From: ", dgettext("privacy-setting",
PRIVACY_MENU_DLP_REPORTS_TOTAL_LEAKS), item->leak_count);
- struct tm *timestamp = gmtime(&item->first_time_stamp);
- size += strftime(string_buf + size, 100 - size, "%b %d, %Y - To: ", timestamp);
+ struct tm timestamp;
+ gmtime_r(&item->first_time_stamp, ×tamp);
+ size += strftime(string_buf + size, 100 - size, "%b %d, %Y - To: ", ×tamp);
- timestamp = gmtime(&item->last_time_stamp);
- size += strftime(string_buf + size, 100 - size, "%b %d, %Y", timestamp);
+ gmtime_r(&item->last_time_stamp, ×tamp);
+ size += strftime(string_buf + size, 100 - size, "%b %d, %Y", ×tamp);
char *multiline = strdup(string_buf);
return "";
char time_str[64] = {0,};
- struct tm *timeinfo = localtime(&item->data->time_stamp);
- strftime(time_str, sizeof(time_str), "%a, %x %X", timeinfo);
+ struct tm timeinfo;
+ localtime_r(&item->data->time_stamp, &timeinfo);
+ strftime(time_str, sizeof(time_str), "%a, %x %X", &timeinfo);
size_t string_mem_needed = snprintf(NULL, 0,
"%s<br>%s",
return "";
char time_str[64] = {0,};
- struct tm *timeinfo = localtime(&item->data->time_stamp);
- strftime(time_str, sizeof(time_str), "%a, %x %X", timeinfo);
+ struct tm timeinfo;
+ localtime_r(&item->data->time_stamp, &timeinfo);
+ strftime(time_str, sizeof(time_str), "%a, %x %X", &timeinfo);
size_t string_mem_needed = snprintf(NULL, 0,
"%s<br>%s",
}
}
+static void add_select_all_item_to_genlist(rule_delete_view_data_s *data)
+{
+ Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
+ itc->item_style = "singleline";
+ itc->func.text_get = _gl_rule_delete_text_get_cb;
+ itc->func.content_get = _gl_rule_delete_content_get_cb;
+ itc->func.del = NULL;
+
+ Elm_Object_Item *it = elm_genlist_item_append(data->genlist, itc, data->rule_item_list->data, NULL, ELM_GENLIST_ITEM_NONE, _rule_delete_menu_item_selected_cb, data);
+ log_if(it == NULL, 1, "Error in elm_genlist_item_append");
+
+ elm_genlist_item_class_free(itc);
+}
+
void create_privacy_dlp_rule_delete_view(struct app_data_s *ad, const GList *rule_list, void *rule_list_data)
{
if (NULL == ad || NULL == rule_list || NULL == rule_list_data) {
evas_object_size_hint_weight_set(data.genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(data.genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ add_select_all_item_to_genlist(&data);
Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
itc->item_style = "multiline";
itc->func.text_get = _gl_rule_delete_text_get_cb;
itc->func.content_get = _gl_rule_delete_content_get_cb;
itc->func.del = NULL;
Elm_Object_Item *it = NULL;
- GList* l = data.rule_item_list;
+ GList* l = g_list_nth(data.rule_item_list, 1);
while (l != NULL) {
// append item to the genlist
log_if(it == NULL, 1, "Error in elm_genlist_item_append");
const get_custom_rule_s *rule = ((rule_delete_item_s *)(l->data))->rule;
- if (SELECT_ALL_RULES_ITEM == rule->id) {
- l = l->next;
- continue;
- }
// Skip rules that have the same pattern and action as the current rule
const int pattern_id = rule->pattern_id;
char name[LEN_NAME];
strncpy(name, get_text_from_edit_field(red->name_edit_field), LEN_NAME);
+ left_trim(name, LEN_NAME);
name[LEN_NAME - 1] = '\0';
char description[LEN_DESCRIPTION];
strncpy(description, get_text_from_edit_field(red->description_edit_field), LEN_DESCRIPTION);
+ left_trim(description, LEN_DESCRIPTION);
description[LEN_DESCRIPTION - 1] = '\0';
const int pattern_id = current_pattern->id;
red->edited_rule.pattern[LEN_PATTERN - 1] = '\0';
strncpy(red->edited_rule.name, get_text_from_edit_field(red->name_edit_field), LEN_NAME);
+ left_trim(red->edited_rule.name, LEN_NAME);
red->edited_rule.name[LEN_NAME - 1] = '\0';
strncpy(red->edited_rule.description, get_text_from_edit_field(red->description_edit_field), LEN_DESCRIPTION);
+ left_trim(red->edited_rule.description, LEN_DESCRIPTION);
red->edited_rule.description[LEN_DESCRIPTION - 1] = '\0';
strncpy(red->edited_rule.application_id, red->current_rule->application_id, LEN_APPLICATION_ID);
static void set_state_of_done_button(rule_edit_data_s *red)
{
- const Eina_Bool disable = !is_edit_field_empty(red->name_edit_field)
- && !is_edit_field_empty(red->description_edit_field)
- && NULL != current_pattern
- ? EINA_FALSE : EINA_TRUE;
+ const Eina_Bool disable = is_valid_rule(
+ get_text_from_edit_field(red->name_edit_field),
+ get_text_from_edit_field(red->description_edit_field),
+ current_pattern) ? EINA_FALSE : EINA_TRUE;
Evas_Object *button = (NULL != red->done_button) ? red->done_button : red->next_button;
elm_object_disabled_set(button, disable);
}