2 * Copyright (c) 2017 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
19 * @author Pawel Kowalski <p.kowalski2@partner.samsung.com>
20 * @brief The implementation of testing application of the PPM CAPI.
24 #include <Elementary.h>
25 #include <system_settings.h>
26 #include <efl_extension.h>
29 #include <privacy_privilege_manager.h>
34 #define LOG_TAG "ppmtester"
36 #define BUFFER_SIZE 1024
39 #define PACKAGE "org.example.ppmtester"
42 typedef struct appdata
50 static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
56 * @brief Prints massage into the message box.
58 * @param[in] obj The message box.
59 * @param[in] msg The text message that is written to the message box.
60 * @param[in] ... Additional arguments declared in the text message.
62 void print_msg(Evas_Object *obj, const char* msg, ...)
66 char buffer[BUFFER_SIZE];
67 vsnprintf(buffer, BUFFER_SIZE, msg, args);
71 elm_entry_entry_append(obj, buffer);
72 elm_entry_entry_append(obj, "<br>");
73 elm_entry_cursor_end_set(obj);
74 elm_entry_cursor_geometry_get(obj, NULL, &c_y, NULL, NULL);
75 elm_scroller_region_show(obj, 0, c_y, 0, 0);
79 * @brief Clears the message box.
81 * @param[in] data User specific data.
82 * @param[in] btn Pointer to the button object.
83 * @param[in] event_info Additional event information.
85 static void _btn_clear_cb(void *data, Evas_Object *btn, void *event_info)
88 elm_entry_entry_set(ad->msg_box, "");
92 * @brief Creates the display object.
94 Evas_Object *_create_new_cd_display(appdata_s *ad, const char *name, void *cb)
97 Evas_Object *scroller = elm_scroller_add(ad->window);
98 evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
101 Elm_Object_Item *item =
102 elm_naviframe_item_push(ad->navi, "PPM Tester", NULL, NULL, scroller, NULL);
103 elm_object_item_part_text_set(item, "subtitle", "Test following privileges:");
106 elm_naviframe_item_pop_cb_set(item, (Elm_Naviframe_Item_Pop_Cb) cb, (void *)ad);
109 Evas_Object *box = elm_box_add(scroller);
110 elm_object_content_set(scroller, box);
111 elm_box_horizontal_set(box, EINA_FALSE);
112 evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
113 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
114 evas_object_show(box);
116 Evas_Object *inner_grid = elm_grid_add(box);
117 elm_object_content_set(box, inner_grid);
118 evas_object_size_hint_align_set(inner_grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
119 evas_object_size_hint_weight_set(inner_grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
120 evas_object_show(inner_grid);
122 Evas_Object *bbox_scroller = elm_scroller_add(inner_grid);
123 evas_object_size_hint_align_set(bbox_scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
124 evas_object_size_hint_weight_set(bbox_scroller, EVAS_HINT_EXPAND, 0.0);
125 elm_scroller_policy_set(bbox_scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
126 elm_object_style_set(bbox_scroller, "handler");
127 evas_object_show(bbox_scroller);
129 // Create a box for adding content
130 Evas_Object *bbox = elm_box_add(bbox_scroller);
131 Evas_Coord padding_between_buttons = 3;
132 elm_box_padding_set(bbox, 0, padding_between_buttons);
133 elm_object_content_set(bbox_scroller, bbox);
134 elm_box_horizontal_set(bbox, EINA_FALSE);
135 evas_object_size_hint_align_set(bbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
136 evas_object_size_hint_weight_set(bbox, EVAS_HINT_EXPAND, 0.0);
137 evas_object_show(bbox);
139 // Create "Clear" button
140 Evas_Object *bt = elm_button_add(box);
141 elm_object_text_set(bt, "Clear");
142 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
143 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
144 evas_object_smart_callback_add(bt, "clicked", _btn_clear_cb, ad);
145 evas_object_show(bt);
147 // Create a box for entry
148 Evas_Object *ebox = elm_box_add(inner_grid);
149 elm_box_horizontal_set(ebox, EINA_FALSE);
150 evas_object_size_hint_align_set(ebox, EVAS_HINT_FILL, EVAS_HINT_FILL);
151 evas_object_size_hint_weight_set(ebox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
152 evas_object_show(ebox);
154 // Create a message box
155 Evas_Object *display_window = elm_entry_add(ebox);
156 evas_object_size_hint_align_set(display_window, EVAS_HINT_FILL, EVAS_HINT_FILL);
157 evas_object_size_hint_weight_set(display_window, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
158 evas_object_show(display_window);
160 elm_entry_editable_set(display_window, EINA_FALSE);
161 elm_entry_scrollable_set(display_window, EINA_TRUE);
163 ad->msg_box = display_window;
164 elm_scroller_policy_set(ad->msg_box, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
165 elm_box_pack_end(ebox, display_window);
167 elm_grid_pack(inner_grid, bbox_scroller, 0, 0, 100, 35);
168 elm_grid_pack(inner_grid, ebox, 0, 35, 100, 65);
169 elm_box_pack_end(box, inner_grid);
170 elm_box_pack_end(box, bt);
175 Eina_Bool _pop_cb(void *data, Elm_Object_Item *item)
177 elm_win_lower(((appdata_s *)data)->window);
182 * @brief Function copied from the Account Manager example.
184 Evas_Object *_new_button(appdata_s *ad, Evas_Object *display, const char *name, void *cb)
187 Evas_Object *bt = elm_button_add(display);
188 elm_object_text_set(bt, name);
189 evas_object_smart_callback_add(bt, "clicked", (Evas_Smart_Cb) cb, ad);
190 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
191 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
192 elm_box_pack_end(display, bt);
193 evas_object_show(bt);
198 * @brief Writes text into dlogutil and into GUI.
200 * @details In order to read a message using dlogutil,
201 * type in the emulator's terminal: dlogutil ppmtester
202 * The 'ppmtester' flag is set using LOG_TAG constant.
204 * @param[in] ad The structure with GUI elements.
205 * @param[in] privilege A privilege that is to be logged.
206 * @param[in] msg A text that is to be written.
208 void log_privilege (appdata_s *ad, const char* privilege, const char* msg)
210 print_msg(ad->msg_box, "----------<br>Privilege: %s<br>Message: %s", privilege, msg);
211 dlog_print(DLOG_INFO, LOG_TAG, "----------\nPrivilege: %s\nMessage: %s", privilege, msg);
215 * @brief Based on ppm_popup_response_cb prototype from privacy-privilege-manager.h.
217 * @param[in] cause A value representing the reason why this callback
219 * @param[in] result A result of a response triggered by calling ppm_popup_request().
220 * @param[in] privilege A privilege that has been checked.
221 * @param[in] user_data User specific data.
223 void ppm_popup_response_cb_function (ppm_call_cause_e cause, ppm_request_result_e result, const char *privilege, void *user_data)
225 appdata_s *ad = user_data;
228 case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER:
229 log_privilege(ad, privilege, "Callback was called with a valid answer.");
232 case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER:
233 log_privilege(ad, privilege, "A user granted permission to use a privilege for an indefinite period of time.");
235 case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_FOREVER:
236 log_privilege(ad, privilege, "A user did not grant permission to use a privilege for an indefinite period of time.");
239 case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_ONCE:
240 log_privilege(ad, privilege, "A user did not grant permission to use a privilege once.");
246 case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR:
247 log_privilege(ad, privilege, "Callback was called because of an error.");
251 char msg[BUFFER_SIZE];
252 snprintf(msg, BUFFER_SIZE, "Unknown cause: %d", cause);
253 log_privilege(ad, privilege, msg);
260 * @brief Checks the privilege. Writes messages in the bottom part of the main window and
261 * into the shell (in order to read these messages use command: dlogutil ppmtester).
263 * @param[in] ad The structure with GUI elements.
264 * @param[in] privilege A privilege that is to be checked.
265 * @param[in] ret The code of the error.
267 void app_log_errors(appdata_s *ad, const char* privilege, ppm_error_e ret)
271 case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR:
272 log_privilege(ad, privilege, "I/O error");
274 case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER:
275 log_privilege(ad, privilege, "Invalid parameter");
277 case PRIVACY_PRIVILEGE_MANAGER_ERROR_ALREADY_IN_PROGRESS:
278 log_privilege(ad, privilege, "Operation already in progress");
280 case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY:
281 log_privilege(ad, privilege, "Out of memory");
283 case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN:
284 log_privilege(ad, privilege, "Unknown error");
287 log_privilege(ad, privilege, "Unknown error");
293 * @brief Checks the privilege. Writes messages in the bottom part of the main window and
294 * into the shell (in order to read these messages use command: dlogutil ppmtester).
296 * @param[in] ad The structure with GUI elements.
297 * @param[in] privilege A privilege that is to be checked.
299 void check_privilege (appdata_s *ad, const char* privilege)
301 ppm_check_result_e result;
303 int ret = ppm_check_permission(privilege, &result);
305 if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) // If there is an error, print log.
307 app_log_errors(ad, privilege, ret);
311 switch (result) // Alow, deny or ask.
313 case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
314 log_privilege(ad, privilege, "An application has permission to use a privilege.");
316 case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY:
317 log_privilege(ad, privilege, "An application doesn't have permission to use a privilege.");
319 case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
321 log_privilege(ad, privilege, "A user has to be asked whether to grant permission to use a privilege.");
322 int ret_popup = ppm_request_permission(privilege, ppm_popup_response_cb_function, ad);
323 if (ret_popup != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE)
325 app_log_errors(ad, privilege, ret_popup);
332 char msg[BUFFER_SIZE];
333 snprintf(msg, BUFFER_SIZE, "Unknown result: %d", result);
334 log_privilege(ad, privilege, msg);
341 * @brief Callback for 'camera' button.
343 * @param[in] ad The structure with GUI elements.
344 * @param[in] obj Display object.
346 void _test_privilege_camera(appdata_s *ad, Evas_Object *obj)
348 check_privilege(ad, "http://tizen.org/privilege/camera");
352 * @brief Callback for 'location' button.
354 * @param[in] ad The structure with GUI elements.
355 * @param[in] obj Display object.
357 void _test_privilege_location(appdata_s *ad, Evas_Object *obj)
359 check_privilege(ad, "http://tizen.org/privilege/location");
363 * @brief Callback for 'contact.read' button.
365 * @param[in] ad The structure with GUI elements.
366 * @param[in] obj Display object.
368 void _test_privilege_contact_read(appdata_s *ad, Evas_Object *obj)
370 check_privilege(ad, "http://tizen.org/privilege/contact.read");
374 * @brief Callback for 'contact.write' button.
376 * @param[in] ad The structure with GUI elements.
377 * @param[in] obj Display object.
379 void _test_privilege_contact_write(appdata_s *ad, Evas_Object *obj)
381 check_privilege(ad, "http://tizen.org/privilege/contact.write");
385 * @brief Creates buttons in the main window.
387 * @param[in] ad The structure with GUI elements.
389 void create_buttons_in_main_window(appdata_s *ad)
391 Evas_Object *display = _create_new_cd_display(ad, "PPM Tester", _pop_cb);
393 _new_button(ad, display, "camera", _test_privilege_camera);
394 _new_button(ad, display, "location", _test_privilege_location);
395 _new_button(ad, display, "contact.read", _test_privilege_contact_read);
396 _new_button(ad, display, "contact.write", _test_privilege_contact_write);
400 * @brief Creates base GUI (window, conformant, naviframe and buttons).
402 * @param[in] ad The structure with GUI elements.
404 static void create_base_gui(appdata_s *ad)
406 // Setting the window
407 ad->window = elm_win_util_standard_add(PACKAGE, PACKAGE);
408 elm_win_conformant_set(ad->window, EINA_TRUE);
409 elm_win_autodel_set(ad->window, EINA_TRUE);
410 elm_win_indicator_mode_set(ad->window, ELM_WIN_INDICATOR_SHOW);
411 elm_win_indicator_opacity_set(ad->window, ELM_WIN_INDICATOR_OPAQUE);
412 evas_object_smart_callback_add(ad->window, "delete, request", win_delete_request_cb, NULL);
415 ad->conform = elm_conformant_add(ad->window);
416 evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
417 elm_win_resize_object_add(ad->window, ad->conform);
418 evas_object_show(ad->conform);
420 // Create a naviframe
421 ad->navi = elm_naviframe_add(ad->conform);
422 evas_object_size_hint_align_set(ad->navi, EVAS_HINT_FILL, EVAS_HINT_FILL);
423 evas_object_size_hint_weight_set(ad->navi, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
425 elm_object_content_set(ad->conform, ad->navi);
426 evas_object_show(ad->navi);
428 // Fill the list with items
429 create_buttons_in_main_window(ad);
431 eext_object_event_callback_add(ad->navi, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
433 // Show the window after base gui is set up
434 evas_object_show(ad->window);
437 static bool app_create(void *data)
440 * Hook to take necessary actions before main event loop starts
441 * Initialize UI resources and application's data
442 * If this function returns true, the main loop of application starts
443 * If this function returns false, the application is terminated
446 appdata_s *ad = data;
453 static void app_control(app_control_h app_control, void *data)
455 // Handle the launch request.
458 static void app_pause(void *data)
460 // Take necessary actions when application becomes invisible.
463 static void app_resume(void *data)
465 // Take necessary actions when application becomes visible.
467 // Checking two example privileges on resume:
468 const char* privileges [] = {"http://tizen.org/privilege/alarm.get", "http://tizen.org/privilege/calendar.read"};
469 for (int i = 0; i < sizeof(privileges)/sizeof(privileges[0]); i++)
471 check_privilege(data, privileges[i]);
475 static void app_terminate(void *data)
477 // Release all resources.
480 int main(int argc, char *argv[])
485 ui_app_lifecycle_callback_s event_callback = {0,};
487 event_callback.create = app_create;
488 event_callback.terminate = app_terminate;
489 event_callback.pause = app_pause;
490 event_callback.resume = app_resume;
491 event_callback.app_control = app_control;
493 ret = ui_app_main(argc, argv, &event_callback, &ad);
494 if (ret != APP_ERROR_NONE)
496 dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);